Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bcafc16cf | ||
|
|
7ba991235b | ||
|
|
926574e107 | ||
|
|
900e52ca27 | ||
|
|
bcb5832c4c | ||
|
|
c4c70d6c9c | ||
|
|
c75b0e5cf0 | ||
|
|
7583d15c9d | ||
|
|
422b5e7884 | ||
|
|
aff4f4ae7d | ||
|
|
a704bb2be3 | ||
|
|
9488df662b | ||
|
|
70e6f81663 | ||
|
|
4ab2a0c53a | ||
|
|
bebd34b1d8 | ||
|
|
7a5b557bb5 | ||
|
|
2ec1cbcd43 | ||
|
|
281706688f | ||
|
|
7d53dd0d9c | ||
|
|
e1eab6a644 | ||
|
|
1c29a8391d | ||
|
|
d9cf355b79 | ||
|
|
3762ccd396 | ||
|
|
7c8e57d6b3 |
No files matched your search
@@ -0,0 +1,285 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// DeepSpeed Team
|
||||||
|
|
||||||
|
#include <ATen/cuda/CUDAContext.h>
|
||||||
|
#include <torch/extension.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include <vector>
|
||||||
|
#include "quantization.h"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
at::Tensor ds_quantize(at::Tensor& vals, int groups, int bits)
|
||||||
|
{
|
||||||
|
auto t_size = vals.sizes();
|
||||||
|
int size = 1;
|
||||||
|
for (auto dim : t_size) size *= dim;
|
||||||
|
|
||||||
|
if ((((size / groups) - 1) / 4096 + 1) <= 256) {
|
||||||
|
launch_fake_quantize_kernel(
|
||||||
|
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||||
|
}
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
at::Tensor ds_sr_quantize(at::Tensor& vals, int groups, int bits)
|
||||||
|
{
|
||||||
|
auto t_size = vals.sizes();
|
||||||
|
int size = 1;
|
||||||
|
for (auto dim : t_size) size *= dim;
|
||||||
|
|
||||||
|
if (((size / groups) / 4 / 1024) <= 256) {
|
||||||
|
launch_sr_fake_quantize_kernel(
|
||||||
|
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||||
|
}
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
at::Tensor ds_quantize_asym(at::Tensor& vals, int groups, int bits)
|
||||||
|
{
|
||||||
|
auto t_size = vals.sizes();
|
||||||
|
int size = 1;
|
||||||
|
for (auto dim : t_size) size *= dim;
|
||||||
|
|
||||||
|
if ((((size / groups) - 1) / 4096 + 1) <= 256) {
|
||||||
|
launch_fake_quantize_kernel_asym(
|
||||||
|
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||||
|
}
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
at::Tensor ds_sr_quantize_asym(at::Tensor& vals, int groups, int bits)
|
||||||
|
{
|
||||||
|
auto t_size = vals.sizes();
|
||||||
|
int size = 1;
|
||||||
|
for (auto dim : t_size) size *= dim;
|
||||||
|
|
||||||
|
if (((size / groups) / 4 / 1024) <= 256) {
|
||||||
|
launch_sr_fake_quantize_kernel_asym(
|
||||||
|
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||||
|
}
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<at::Tensor> quantize_kernel(at::Tensor& input_vals,
|
||||||
|
int groups,
|
||||||
|
int numBits,
|
||||||
|
quantize::Type quantType)
|
||||||
|
{
|
||||||
|
auto dtype = at::kFloat;
|
||||||
|
auto params_options = at::TensorOptions()
|
||||||
|
.dtype(dtype)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
const int param_elems = (quantize::requires_offset(quantType)) ? 2 : 1;
|
||||||
|
auto params = torch::empty({groups, param_elems}, params_options);
|
||||||
|
|
||||||
|
auto output_options = at::TensorOptions()
|
||||||
|
.dtype(at::kChar)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
|
||||||
|
auto output_sizes = input_vals.sizes().vec();
|
||||||
|
output_sizes[output_sizes.size() - 1] /= numBits == 8 ? 1 : 2;
|
||||||
|
auto output = torch::empty(output_sizes, output_options);
|
||||||
|
|
||||||
|
const int elems_per_group = at::numel(input_vals) / groups;
|
||||||
|
|
||||||
|
launch_quant((int8_t*)output.data_ptr(),
|
||||||
|
(float*)params.data_ptr(),
|
||||||
|
(__half*)input_vals.data_ptr(),
|
||||||
|
groups,
|
||||||
|
elems_per_group,
|
||||||
|
numBits,
|
||||||
|
quantType,
|
||||||
|
at::cuda::getCurrentCUDAStream());
|
||||||
|
|
||||||
|
return {output, params};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
at::Tensor dequantize(at::Tensor& quantized_data,
|
||||||
|
at::Tensor& params,
|
||||||
|
int groups,
|
||||||
|
int num_bits,
|
||||||
|
quantize::Type quant_type)
|
||||||
|
{
|
||||||
|
auto dtype = (std::is_same<T, float>::value) ? torch::kFloat32 : torch::kFloat16;
|
||||||
|
auto output_options = at::TensorOptions()
|
||||||
|
.dtype(dtype)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
|
||||||
|
auto output_sizes = quantized_data.sizes().vec();
|
||||||
|
output_sizes[output_sizes.size() - 1] *= num_bits == 8 ? 1 : 2;
|
||||||
|
auto output = torch::empty(output_sizes, output_options);
|
||||||
|
|
||||||
|
const int total_elems = at::numel(output);
|
||||||
|
const int elems_per_group = total_elems / groups;
|
||||||
|
|
||||||
|
launch_dequantize_kernel((T*)output.data_ptr(),
|
||||||
|
(const int8_t*)quantized_data.data_ptr(),
|
||||||
|
(const float*)params.data_ptr(),
|
||||||
|
quant_type,
|
||||||
|
num_bits,
|
||||||
|
elems_per_group,
|
||||||
|
total_elems,
|
||||||
|
at::cuda::getCurrentCUDAStream());
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
at::Tensor dequantize_int4_to_half_experimental(at::Tensor& data_in,
|
||||||
|
at::Tensor& scale_buffer,
|
||||||
|
at::Tensor& min_val_buffer,
|
||||||
|
int num_group,
|
||||||
|
int group_size)
|
||||||
|
{
|
||||||
|
auto output_options = at::TensorOptions().dtype(at::kHalf).device(at::kCUDA);
|
||||||
|
auto output = torch::empty({num_group, group_size}, output_options);
|
||||||
|
|
||||||
|
launch_dequantize_int4_to_half_experimental((uint8_t*)data_in.data_ptr(),
|
||||||
|
(half*)output.data_ptr(),
|
||||||
|
(half*)scale_buffer.data_ptr(),
|
||||||
|
(half*)min_val_buffer.data_ptr(),
|
||||||
|
num_group,
|
||||||
|
group_size,
|
||||||
|
at::cuda::getCurrentCUDAStream());
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<at::Tensor> ds_swizzle_quant(at::Tensor& input_vals,
|
||||||
|
int groups,
|
||||||
|
int num_bits,
|
||||||
|
quantize::Type quant_type,
|
||||||
|
int pipeline_size,
|
||||||
|
int nodes,
|
||||||
|
int devices_per_node)
|
||||||
|
{
|
||||||
|
auto scales_options = at::TensorOptions()
|
||||||
|
.dtype(at::kFloat)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
const int scales_elems = (quantize::requires_offset(quant_type)) ? 2 : 1;
|
||||||
|
auto scales = torch::empty({groups, scales_elems}, scales_options);
|
||||||
|
|
||||||
|
auto output_options = at::TensorOptions()
|
||||||
|
.dtype(at::kChar)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
|
||||||
|
const int quantization_scalar = 8 / num_bits;
|
||||||
|
const int compressed_vals = at::numel(input_vals) / quantization_scalar;
|
||||||
|
|
||||||
|
auto output = torch::empty({compressed_vals}, output_options);
|
||||||
|
const int elems_per_group = at::numel(input_vals) / groups;
|
||||||
|
|
||||||
|
launch_swizzled_quant((int8_t*)output.data_ptr(),
|
||||||
|
(float*)scales.data_ptr(),
|
||||||
|
(__half*)input_vals.data_ptr(),
|
||||||
|
num_bits,
|
||||||
|
quant_type,
|
||||||
|
groups,
|
||||||
|
elems_per_group,
|
||||||
|
pipeline_size,
|
||||||
|
nodes,
|
||||||
|
devices_per_node,
|
||||||
|
at::cuda::getCurrentCUDAStream());
|
||||||
|
|
||||||
|
return {output, scales};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<at::Tensor> quantized_reduction(at::Tensor& input_vals,
|
||||||
|
at::Tensor& input_scales,
|
||||||
|
int in_groups,
|
||||||
|
int out_groups,
|
||||||
|
int num_bits,
|
||||||
|
quantize::Type quant_type,
|
||||||
|
int devices_per_node)
|
||||||
|
{
|
||||||
|
auto scales_options = at::TensorOptions()
|
||||||
|
.dtype(at::kFloat)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
const int scales_elems = (quantize::requires_offset(quant_type)) ? 2 : 1;
|
||||||
|
auto scales = torch::empty({out_groups, scales_elems}, scales_options);
|
||||||
|
|
||||||
|
auto output_options = at::TensorOptions()
|
||||||
|
.dtype(at::kChar)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
|
||||||
|
std::vector<int64_t> sz_vector(input_vals.sizes().begin(), input_vals.sizes().end());
|
||||||
|
sz_vector[sz_vector.size() - 1] = sz_vector.back() / devices_per_node; // num of GPU per nodes
|
||||||
|
at::IntArrayRef sz(sz_vector);
|
||||||
|
auto output = torch::empty(sz, output_options);
|
||||||
|
|
||||||
|
const int elems_per_in_tensor = at::numel(input_vals) / devices_per_node;
|
||||||
|
const int elems_per_in_group = elems_per_in_tensor / (in_groups / devices_per_node);
|
||||||
|
const int elems_per_out_group = elems_per_in_tensor / out_groups;
|
||||||
|
|
||||||
|
// old code:
|
||||||
|
// std::vector<long int> sz(input_vals.sizes().begin(), input_vals.sizes().end());
|
||||||
|
// sz[sz.size() - 1] = sz.back() / devices_per_node; // num of GPU per nodes
|
||||||
|
// const int elems_per_in_tensor = at::numel(input_vals) / devices_per_node;
|
||||||
|
// auto output = torch::empty(sz, output_options);
|
||||||
|
|
||||||
|
// const int elems_per_in_group = elems_per_in_tensor / (in_groups / devices_per_node);
|
||||||
|
// const int elems_per_out_group = elems_per_in_tensor / out_groups;
|
||||||
|
|
||||||
|
launch_dequant_reduce((int8_t*)output.data_ptr(),
|
||||||
|
(float*)scales.data_ptr(),
|
||||||
|
(const int8_t*)input_vals.data_ptr(),
|
||||||
|
(const float*)input_scales.data_ptr(),
|
||||||
|
devices_per_node,
|
||||||
|
num_bits,
|
||||||
|
quant_type,
|
||||||
|
out_groups,
|
||||||
|
elems_per_out_group,
|
||||||
|
elems_per_in_tensor,
|
||||||
|
in_groups / devices_per_node,
|
||||||
|
elems_per_in_group,
|
||||||
|
at::cuda::getCurrentCUDAStream());
|
||||||
|
return {output, scales};
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m)
|
||||||
|
{
|
||||||
|
m.def("ds_quantize_fp32", &ds_quantize<float>, "DeepSpeed Quantize with fp32 (CUDA)");
|
||||||
|
m.def("ds_quantize_fp16", &ds_quantize<__half>, "DeepSpeed Quantize with fp16 (CUDA)");
|
||||||
|
m.def("ds_sr_quantize_fp32", &ds_sr_quantize<float>, "DeepSpeed Quantize with fp32 (CUDA)");
|
||||||
|
m.def("ds_sr_quantize_fp16", &ds_sr_quantize<__half>, "DeepSpeed Quantize with fp16 (CUDA)");
|
||||||
|
m.def("ds_quantize_asym_fp32", &ds_quantize_asym<float>, "DeepSpeed Quantize with fp32 (CUDA)");
|
||||||
|
m.def(
|
||||||
|
"ds_quantize_asym_fp16", &ds_quantize_asym<__half>, "DeepSpeed Quantize with fp16 (CUDA)");
|
||||||
|
m.def("ds_sr_quantize_asym_fp32",
|
||||||
|
&ds_sr_quantize_asym<float>,
|
||||||
|
"DeepSpeed Quantize with fp32 (CUDA)");
|
||||||
|
m.def("ds_sr_quantize_asym_fp16",
|
||||||
|
&ds_sr_quantize_asym<__half>,
|
||||||
|
"DeepSpeed Quantize with fp16 (CUDA)");
|
||||||
|
pybind11::enum_<quantize::Type>(m, "QuantizationType")
|
||||||
|
.value("Symmetric", quantize::Type::Symmetric)
|
||||||
|
.value("Asymmetric", quantize::Type::Asymmetric)
|
||||||
|
.export_values();
|
||||||
|
m.def("quantize", &quantize_kernel);
|
||||||
|
m.def("dequantize", &dequantize<__half>);
|
||||||
|
m.def("dequantize_fp32", &dequantize<float>);
|
||||||
|
m.def("dequantize_int4_to_half_experimental",
|
||||||
|
&dequantize_int4_to_half_experimental,
|
||||||
|
"Dequantize int4 to half (experimental)");
|
||||||
|
m.def("swizzle_quant", &ds_swizzle_quant);
|
||||||
|
m.def("quantized_reduction", &quantized_reduction);
|
||||||
|
}
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,160 @@
|
|||||||
|
# Copyright (c) Microsoft Corporation.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
# DeepSpeed Team
|
||||||
|
|
||||||
|
import os
|
||||||
|
import torch
|
||||||
|
import deepspeed
|
||||||
|
import subprocess
|
||||||
|
import argparse
|
||||||
|
import psutil
|
||||||
|
from .ops.op_builder.all_ops import ALL_OPS
|
||||||
|
from .git_version_info import installed_ops, torch_info
|
||||||
|
from deepspeed.accelerator import get_accelerator
|
||||||
|
|
||||||
|
GREEN = '\033[92m'
|
||||||
|
RED = '\033[91m'
|
||||||
|
YELLOW = '\033[93m'
|
||||||
|
END = '\033[0m'
|
||||||
|
SUCCESS = f"{GREEN} [SUCCESS] {END}"
|
||||||
|
OKAY = f"{GREEN}[OKAY]{END}"
|
||||||
|
WARNING = f"{YELLOW}[WARNING]{END}"
|
||||||
|
FAIL = f'{RED}[FAIL]{END}'
|
||||||
|
INFO = '[INFO]'
|
||||||
|
|
||||||
|
color_len = len(GREEN) + len(END)
|
||||||
|
okay = f"{GREEN}[OKAY]{END}"
|
||||||
|
warning = f"{YELLOW}[WARNING]{END}"
|
||||||
|
|
||||||
|
|
||||||
|
def op_report(verbose=True):
|
||||||
|
max_dots = 23
|
||||||
|
max_dots2 = 11
|
||||||
|
h = ["op name", "installed", "compatible"]
|
||||||
|
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||||
|
print("DeepSpeed C++/CUDA extension op report")
|
||||||
|
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||||
|
|
||||||
|
print("NOTE: Ops not installed will be just-in-time (JIT) compiled at\n"
|
||||||
|
" runtime if needed. Op compatibility means that your system\n"
|
||||||
|
" meet the required dependencies to JIT install the op.")
|
||||||
|
|
||||||
|
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||||
|
print("JIT compiled ops requires ninja")
|
||||||
|
ninja_status = OKAY if ninja_installed() else FAIL
|
||||||
|
print('ninja', "." * (max_dots - 5), ninja_status)
|
||||||
|
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||||
|
print(h[0], "." * (max_dots - len(h[0])), h[1], "." * (max_dots2 - len(h[1])), h[2])
|
||||||
|
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||||
|
installed = f"{GREEN}[YES]{END}"
|
||||||
|
no = f"{YELLOW}[NO]{END}"
|
||||||
|
for op_name, builder in ALL_OPS.items():
|
||||||
|
dots = "." * (max_dots - len(op_name))
|
||||||
|
is_compatible = OKAY if builder.is_compatible(verbose) else no
|
||||||
|
is_installed = installed if installed_ops.get(op_name, False) else no
|
||||||
|
dots2 = '.' * ((len(h[1]) + (max_dots2 - len(h[1]))) - (len(is_installed) - color_len))
|
||||||
|
print(op_name, dots, is_installed, dots2, is_compatible)
|
||||||
|
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||||
|
|
||||||
|
|
||||||
|
def ninja_installed():
|
||||||
|
try:
|
||||||
|
import ninja # noqa: F401 # type: ignore
|
||||||
|
except ImportError:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def nvcc_version():
|
||||||
|
import torch.utils.cpp_extension
|
||||||
|
cuda_home = torch.utils.cpp_extension.CUDA_HOME
|
||||||
|
if cuda_home is None:
|
||||||
|
return f"{RED} [FAIL] cannot find CUDA_HOME via torch.utils.cpp_extension.CUDA_HOME={torch.utils.cpp_extension.CUDA_HOME} {END}"
|
||||||
|
try:
|
||||||
|
output = subprocess.check_output([cuda_home + "/bin/nvcc", "-V"], universal_newlines=True)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return f"{RED} [FAIL] nvcc missing {END}"
|
||||||
|
output_split = output.split()
|
||||||
|
release_idx = output_split.index("release")
|
||||||
|
release = output_split[release_idx + 1].replace(',', '').split(".")
|
||||||
|
return ".".join(release)
|
||||||
|
|
||||||
|
|
||||||
|
def get_shm_size():
|
||||||
|
try:
|
||||||
|
temp_dir = os.getenv('TEMP') or os.getenv('TMP') or os.path.join(os.path.expanduser('~'), 'tmp')
|
||||||
|
shm_stats = psutil.disk_usage(temp_dir)
|
||||||
|
shm_size = shm_stats.total
|
||||||
|
shm_hbytes = human_readable_size(shm_size)
|
||||||
|
warn = []
|
||||||
|
if shm_size < 512 * 1024**2:
|
||||||
|
warn.append(
|
||||||
|
f" {YELLOW} [WARNING] Shared memory size might be too small, consider increasing it. {END}"
|
||||||
|
)
|
||||||
|
# Add additional warnings specific to your use case if needed.
|
||||||
|
return shm_hbytes, warn
|
||||||
|
except Exception as e:
|
||||||
|
return "UNKNOWN", [f"Error getting shared memory size: {e}"]
|
||||||
|
|
||||||
|
def human_readable_size(size):
|
||||||
|
units = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||||
|
i = 0
|
||||||
|
while size >= 1024 and i < len(units) - 1:
|
||||||
|
size /= 1024
|
||||||
|
i += 1
|
||||||
|
return f'{size:.2f} {units[i]}'
|
||||||
|
|
||||||
|
|
||||||
|
def debug_report():
|
||||||
|
max_dots = 33
|
||||||
|
|
||||||
|
report = [("torch install path", torch.__path__), ("torch version", torch.__version__),
|
||||||
|
("deepspeed install path", deepspeed.__path__),
|
||||||
|
("deepspeed info", f"{deepspeed.__version__}, {deepspeed.__git_hash__}, {deepspeed.__git_branch__}")]
|
||||||
|
if get_accelerator().device_name() == 'cuda':
|
||||||
|
hip_version = getattr(torch.version, "hip", None)
|
||||||
|
report.extend([("torch cuda version", torch.version.cuda), ("torch hip version", hip_version),
|
||||||
|
("nvcc version", (None if hip_version else nvcc_version())),
|
||||||
|
("deepspeed wheel compiled w.", f"torch {torch_info['version']}, " +
|
||||||
|
(f"hip {torch_info['hip_version']}" if hip_version else f"cuda {torch_info['cuda_version']}"))
|
||||||
|
])
|
||||||
|
else:
|
||||||
|
report.extend([("deepspeed wheel compiled w.", f"torch {torch_info['version']} ")])
|
||||||
|
|
||||||
|
report.append(("shared memory (/dev/shm) size", get_shm_size()))
|
||||||
|
|
||||||
|
print("DeepSpeed general environment info:")
|
||||||
|
for name, value in report:
|
||||||
|
warns = []
|
||||||
|
if isinstance(value, tuple):
|
||||||
|
value, warns = value
|
||||||
|
print(name, "." * (max_dots - len(name)), value)
|
||||||
|
if warns:
|
||||||
|
for warn in warns:
|
||||||
|
print(warn)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_arguments():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--hide_operator_status',
|
||||||
|
action='store_true',
|
||||||
|
help='Suppress display of installation and compatibility statuses of DeepSpeed operators. ')
|
||||||
|
parser.add_argument('--hide_errors_and_warnings', action='store_true', help='Suppress warning and error messages.')
|
||||||
|
args = parser.parse_args()
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def main(hide_operator_status=False, hide_errors_and_warnings=False):
|
||||||
|
if not hide_operator_status:
|
||||||
|
op_report(verbose=not hide_errors_and_warnings)
|
||||||
|
debug_report()
|
||||||
|
|
||||||
|
|
||||||
|
def cli_main():
|
||||||
|
args = parse_arguments()
|
||||||
|
main(hide_operator_status=args.hide_operator_status, hide_errors_and_warnings=args.hide_errors_and_warnings)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,299 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// DeepSpeed Team
|
||||||
|
|
||||||
|
#include <ATen/cuda/CUDAContext.h>
|
||||||
|
#include <torch/extension.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include <vector>
|
||||||
|
#include "quantization.h"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
at::Tensor ds_quantize(at::Tensor& vals, int groups, int bits)
|
||||||
|
{
|
||||||
|
auto t_size = vals.sizes();
|
||||||
|
int size = 1;
|
||||||
|
for (auto dim : t_size) size *= dim;
|
||||||
|
|
||||||
|
if ((((size / groups) - 1) / 4096 + 1) <= 256) {
|
||||||
|
launch_fake_quantize_kernel(
|
||||||
|
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||||
|
}
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
at::Tensor ds_sr_quantize(at::Tensor& vals, int groups, int bits)
|
||||||
|
{
|
||||||
|
auto t_size = vals.sizes();
|
||||||
|
int size = 1;
|
||||||
|
for (auto dim : t_size) size *= dim;
|
||||||
|
|
||||||
|
if (((size / groups) / 4 / 1024) <= 256) {
|
||||||
|
launch_sr_fake_quantize_kernel(
|
||||||
|
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||||
|
}
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
at::Tensor ds_quantize_asym(at::Tensor& vals, int groups, int bits)
|
||||||
|
{
|
||||||
|
auto t_size = vals.sizes();
|
||||||
|
int size = 1;
|
||||||
|
for (auto dim : t_size) size *= dim;
|
||||||
|
|
||||||
|
if ((((size / groups) - 1) / 4096 + 1) <= 256) {
|
||||||
|
launch_fake_quantize_kernel_asym(
|
||||||
|
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||||
|
}
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
at::Tensor ds_sr_quantize_asym(at::Tensor& vals, int groups, int bits)
|
||||||
|
{
|
||||||
|
auto t_size = vals.sizes();
|
||||||
|
int size = 1;
|
||||||
|
for (auto dim : t_size) size *= dim;
|
||||||
|
|
||||||
|
if (((size / groups) / 4 / 1024) <= 256) {
|
||||||
|
launch_sr_fake_quantize_kernel_asym(
|
||||||
|
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||||
|
}
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<at::Tensor> quantize_kernel(at::Tensor& input_vals,
|
||||||
|
int groups,
|
||||||
|
int numBits,
|
||||||
|
quantize::Type quantType)
|
||||||
|
{
|
||||||
|
auto dtype = at::kFloat;
|
||||||
|
auto params_options = at::TensorOptions()
|
||||||
|
.dtype(dtype)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
const int param_elems = (quantize::requires_offset(quantType)) ? 2 : 1;
|
||||||
|
auto params = torch::empty({groups, param_elems}, params_options);
|
||||||
|
|
||||||
|
auto output_options = at::TensorOptions()
|
||||||
|
.dtype(at::kChar)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
|
||||||
|
auto output_sizes = input_vals.sizes().vec();
|
||||||
|
output_sizes[output_sizes.size() - 1] /= numBits == 8 ? 1 : 2;
|
||||||
|
auto output = torch::empty(output_sizes, output_options);
|
||||||
|
|
||||||
|
const int elems_per_group = at::numel(input_vals) / groups;
|
||||||
|
|
||||||
|
launch_quant((int8_t*)output.data_ptr(),
|
||||||
|
(float*)params.data_ptr(),
|
||||||
|
(__half*)input_vals.data_ptr(),
|
||||||
|
groups,
|
||||||
|
elems_per_group,
|
||||||
|
numBits,
|
||||||
|
quantType,
|
||||||
|
at::cuda::getCurrentCUDAStream());
|
||||||
|
|
||||||
|
return {output, params};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
at::Tensor dequantize(at::Tensor& quantized_data,
|
||||||
|
at::Tensor& params,
|
||||||
|
int groups,
|
||||||
|
int num_bits,
|
||||||
|
quantize::Type quant_type)
|
||||||
|
{
|
||||||
|
auto dtype = (std::is_same<T, float>::value) ? torch::kFloat32 : torch::kFloat16;
|
||||||
|
auto output_options = at::TensorOptions()
|
||||||
|
.dtype(dtype)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
|
||||||
|
auto output_sizes = quantized_data.sizes().vec();
|
||||||
|
output_sizes[output_sizes.size() - 1] *= num_bits == 8 ? 1 : 2;
|
||||||
|
auto output = torch::empty(output_sizes, output_options);
|
||||||
|
|
||||||
|
const int total_elems = at::numel(output);
|
||||||
|
const int elems_per_group = total_elems / groups;
|
||||||
|
|
||||||
|
launch_dequantize_kernel((T*)output.data_ptr(),
|
||||||
|
(const int8_t*)quantized_data.data_ptr(),
|
||||||
|
(const float*)params.data_ptr(),
|
||||||
|
quant_type,
|
||||||
|
num_bits,
|
||||||
|
elems_per_group,
|
||||||
|
total_elems,
|
||||||
|
at::cuda::getCurrentCUDAStream());
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
at::Tensor dequantize_int4_to_half_experimental(at::Tensor& data_in,
|
||||||
|
at::Tensor& scale_buffer,
|
||||||
|
at::Tensor& min_val_buffer,
|
||||||
|
int num_group,
|
||||||
|
int group_size)
|
||||||
|
{
|
||||||
|
auto output_options = at::TensorOptions().dtype(at::kHalf).device(at::kCUDA);
|
||||||
|
auto output = torch::empty({num_group, group_size}, output_options);
|
||||||
|
|
||||||
|
launch_dequantize_int4_to_half_experimental((uint8_t*)data_in.data_ptr(),
|
||||||
|
(half*)output.data_ptr(),
|
||||||
|
(half*)scale_buffer.data_ptr(),
|
||||||
|
(half*)min_val_buffer.data_ptr(),
|
||||||
|
num_group,
|
||||||
|
group_size,
|
||||||
|
at::cuda::getCurrentCUDAStream());
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
at::Tensor dequantize_int8_to_half_experimental(at::Tensor& data_in,
|
||||||
|
at::Tensor& scale_buffer,
|
||||||
|
at::Tensor& min_val_buffer,
|
||||||
|
int num_group,
|
||||||
|
int group_size)
|
||||||
|
{
|
||||||
|
auto output_options = at::TensorOptions().dtype(at::kHalf).device(at::kCUDA);
|
||||||
|
auto output = torch::empty({num_group, group_size}, output_options);
|
||||||
|
|
||||||
|
launch_dequantize_int8_to_half_experimental((uint8_t*)data_in.data_ptr(),
|
||||||
|
(half*)output.data_ptr(),
|
||||||
|
(half*)scale_buffer.data_ptr(),
|
||||||
|
(half*)min_val_buffer.data_ptr(),
|
||||||
|
num_group,
|
||||||
|
group_size,
|
||||||
|
at::cuda::getCurrentCUDAStream());
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<at::Tensor> ds_swizzle_quant(at::Tensor& input_vals,
|
||||||
|
int groups,
|
||||||
|
int num_bits,
|
||||||
|
quantize::Type quant_type,
|
||||||
|
int pipeline_size,
|
||||||
|
int nodes,
|
||||||
|
int devices_per_node)
|
||||||
|
{
|
||||||
|
auto scales_options = at::TensorOptions()
|
||||||
|
.dtype(at::kFloat)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
const int scales_elems = (quantize::requires_offset(quant_type)) ? 2 : 1;
|
||||||
|
auto scales = torch::empty({groups, scales_elems}, scales_options);
|
||||||
|
|
||||||
|
auto output_options = at::TensorOptions()
|
||||||
|
.dtype(at::kChar)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
|
||||||
|
const int quantization_scalar = 8 / num_bits;
|
||||||
|
const int compressed_vals = at::numel(input_vals) / quantization_scalar;
|
||||||
|
|
||||||
|
auto output = torch::empty({compressed_vals}, output_options);
|
||||||
|
const int elems_per_group = at::numel(input_vals) / groups;
|
||||||
|
|
||||||
|
launch_swizzled_quant((int8_t*)output.data_ptr(),
|
||||||
|
(float*)scales.data_ptr(),
|
||||||
|
(__half*)input_vals.data_ptr(),
|
||||||
|
num_bits,
|
||||||
|
quant_type,
|
||||||
|
groups,
|
||||||
|
elems_per_group,
|
||||||
|
pipeline_size,
|
||||||
|
nodes,
|
||||||
|
devices_per_node,
|
||||||
|
at::cuda::getCurrentCUDAStream());
|
||||||
|
|
||||||
|
return {output, scales};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<at::Tensor> quantized_reduction(at::Tensor& input_vals,
|
||||||
|
at::Tensor& input_scales,
|
||||||
|
int in_groups,
|
||||||
|
int out_groups,
|
||||||
|
int num_bits,
|
||||||
|
quantize::Type quant_type,
|
||||||
|
int devices_per_node)
|
||||||
|
{
|
||||||
|
auto scales_options = at::TensorOptions()
|
||||||
|
.dtype(at::kFloat)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
const int scales_elems = (quantize::requires_offset(quant_type)) ? 2 : 1;
|
||||||
|
auto scales = torch::empty({out_groups, scales_elems}, scales_options);
|
||||||
|
|
||||||
|
auto output_options = at::TensorOptions()
|
||||||
|
.dtype(at::kChar)
|
||||||
|
.layout(at::kStrided)
|
||||||
|
.device(at::kCUDA)
|
||||||
|
.requires_grad(false);
|
||||||
|
|
||||||
|
std::vector<int64_t> sz_vector(input_vals.sizes().begin(), input_vals.sizes().end());
|
||||||
|
sz_vector[sz_vector.size() - 1] = sz_vector.back() / devices_per_node; // num of GPU per nodes
|
||||||
|
at::IntArrayRef sz(sz_vector);
|
||||||
|
auto output = torch::empty(sz, output_options);
|
||||||
|
|
||||||
|
const int elems_per_in_tensor = at::numel(input_vals) / devices_per_node;
|
||||||
|
const int elems_per_in_group = elems_per_in_tensor / (in_groups / devices_per_node);
|
||||||
|
const int elems_per_out_group = elems_per_in_tensor / out_groups;
|
||||||
|
|
||||||
|
launch_dequant_reduce((int8_t*)output.data_ptr(),
|
||||||
|
(float*)scales.data_ptr(),
|
||||||
|
(const int8_t*)input_vals.data_ptr(),
|
||||||
|
(const float*)input_scales.data_ptr(),
|
||||||
|
devices_per_node,
|
||||||
|
num_bits,
|
||||||
|
quant_type,
|
||||||
|
out_groups,
|
||||||
|
elems_per_out_group,
|
||||||
|
elems_per_in_tensor,
|
||||||
|
in_groups / devices_per_node,
|
||||||
|
elems_per_in_group,
|
||||||
|
at::cuda::getCurrentCUDAStream());
|
||||||
|
return {output, scales};
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m)
|
||||||
|
{
|
||||||
|
m.def("ds_quantize_fp32", &ds_quantize<float>, "DeepSpeed Quantize with fp32 (CUDA)");
|
||||||
|
m.def("ds_quantize_fp16", &ds_quantize<__half>, "DeepSpeed Quantize with fp16 (CUDA)");
|
||||||
|
m.def("ds_sr_quantize_fp32", &ds_sr_quantize<float>, "DeepSpeed Quantize with fp32 (CUDA)");
|
||||||
|
m.def("ds_sr_quantize_fp16", &ds_sr_quantize<__half>, "DeepSpeed Quantize with fp16 (CUDA)");
|
||||||
|
m.def("ds_quantize_asym_fp32", &ds_quantize_asym<float>, "DeepSpeed Quantize with fp32 (CUDA)");
|
||||||
|
m.def(
|
||||||
|
"ds_quantize_asym_fp16", &ds_quantize_asym<__half>, "DeepSpeed Quantize with fp16 (CUDA)");
|
||||||
|
m.def("ds_sr_quantize_asym_fp32",
|
||||||
|
&ds_sr_quantize_asym<float>,
|
||||||
|
"DeepSpeed Quantize with fp32 (CUDA)");
|
||||||
|
m.def("ds_sr_quantize_asym_fp16",
|
||||||
|
&ds_sr_quantize_asym<__half>,
|
||||||
|
"DeepSpeed Quantize with fp16 (CUDA)");
|
||||||
|
pybind11::enum_<quantize::Type>(m, "QuantizationType")
|
||||||
|
.value("Symmetric", quantize::Type::Symmetric)
|
||||||
|
.value("Asymmetric", quantize::Type::Asymmetric)
|
||||||
|
.export_values();
|
||||||
|
m.def("quantize", &quantize_kernel);
|
||||||
|
m.def("dequantize", &dequantize<__half>);
|
||||||
|
m.def("dequantize_fp32", &dequantize<float>);
|
||||||
|
m.def("dequantize_int4_to_half_experimental",
|
||||||
|
&dequantize_int4_to_half_experimental,
|
||||||
|
"Dequantize int4 to half (experimental)");
|
||||||
|
m.def("dequantize_int8_to_half_experimental",
|
||||||
|
&dequantize_int8_to_half_experimental,
|
||||||
|
"Dequantize int8 to half (experimental)");
|
||||||
|
m.def("swizzle_quant", &ds_swizzle_quant);
|
||||||
|
m.def("quantized_reduction", &quantized_reduction);
|
||||||
|
}
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,161 @@
|
|||||||
|
# Copyright (c) Microsoft Corporation.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
# DeepSpeed Team
|
||||||
|
|
||||||
|
import os
|
||||||
|
import torch
|
||||||
|
import deepspeed
|
||||||
|
import subprocess
|
||||||
|
import argparse
|
||||||
|
import psutil
|
||||||
|
from .ops.op_builder.all_ops import ALL_OPS
|
||||||
|
from .git_version_info import installed_ops, torch_info
|
||||||
|
from deepspeed.accelerator import get_accelerator
|
||||||
|
|
||||||
|
GREEN = '\033[92m'
|
||||||
|
RED = '\033[91m'
|
||||||
|
YELLOW = '\033[93m'
|
||||||
|
END = '\033[0m'
|
||||||
|
SUCCESS = f"{GREEN} [SUCCESS] {END}"
|
||||||
|
OKAY = f"{GREEN}[OKAY]{END}"
|
||||||
|
WARNING = f"{YELLOW}[WARNING]{END}"
|
||||||
|
FAIL = f'{RED}[FAIL]{END}'
|
||||||
|
INFO = '[INFO]'
|
||||||
|
|
||||||
|
color_len = len(GREEN) + len(END)
|
||||||
|
okay = f"{GREEN}[OKAY]{END}"
|
||||||
|
warning = f"{YELLOW}[WARNING]{END}"
|
||||||
|
|
||||||
|
|
||||||
|
def op_report(verbose=True):
|
||||||
|
max_dots = 23
|
||||||
|
max_dots2 = 11
|
||||||
|
h = ["op name", "installed", "compatible"]
|
||||||
|
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||||
|
print("DeepSpeed C++/CUDA extension op report")
|
||||||
|
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||||
|
|
||||||
|
print("NOTE: Ops not installed will be just-in-time (JIT) compiled at\n"
|
||||||
|
" runtime if needed. Op compatibility means that your system\n"
|
||||||
|
" meet the required dependencies to JIT install the op.")
|
||||||
|
|
||||||
|
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||||
|
print("JIT compiled ops requires ninja")
|
||||||
|
ninja_status = OKAY if ninja_installed() else FAIL
|
||||||
|
print('ninja', "." * (max_dots - 5), ninja_status)
|
||||||
|
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||||
|
print(h[0], "." * (max_dots - len(h[0])), h[1], "." * (max_dots2 - len(h[1])), h[2])
|
||||||
|
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||||
|
installed = f"{GREEN}[YES]{END}"
|
||||||
|
no = f"{YELLOW}[NO]{END}"
|
||||||
|
for op_name, builder in ALL_OPS.items():
|
||||||
|
dots = "." * (max_dots - len(op_name))
|
||||||
|
is_compatible = OKAY if builder.is_compatible(verbose) else no
|
||||||
|
is_installed = installed if installed_ops.get(op_name, False) else no
|
||||||
|
dots2 = '.' * ((len(h[1]) + (max_dots2 - len(h[1]))) - (len(is_installed) - color_len))
|
||||||
|
print(op_name, dots, is_installed, dots2, is_compatible)
|
||||||
|
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||||
|
|
||||||
|
|
||||||
|
def ninja_installed():
|
||||||
|
try:
|
||||||
|
import ninja # noqa: F401 # type: ignore
|
||||||
|
except ImportError:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def nvcc_version():
|
||||||
|
import torch.utils.cpp_extension
|
||||||
|
cuda_home = torch.utils.cpp_extension.CUDA_HOME
|
||||||
|
if cuda_home is None:
|
||||||
|
return f"{RED} [FAIL] cannot find CUDA_HOME via torch.utils.cpp_extension.CUDA_HOME={torch.utils.cpp_extension.CUDA_HOME} {END}"
|
||||||
|
try:
|
||||||
|
output = subprocess.check_output([cuda_home + "/bin/nvcc", "-V"], universal_newlines=True)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return f"{RED} [FAIL] nvcc missing {END}"
|
||||||
|
output_split = output.split()
|
||||||
|
release_idx = output_split.index("release")
|
||||||
|
release = output_split[release_idx + 1].replace(',', '').split(".")
|
||||||
|
return ".".join(release)
|
||||||
|
|
||||||
|
|
||||||
|
def get_shm_size():
|
||||||
|
try:
|
||||||
|
temp_dir = os.getenv('TEMP') or os.getenv('TMP') or os.path.join(os.path.expanduser('~'), 'tmp')
|
||||||
|
shm_stats = psutil.disk_usage(temp_dir)
|
||||||
|
shm_size = shm_stats.total
|
||||||
|
shm_hbytes = human_readable_size(shm_size)
|
||||||
|
warn = []
|
||||||
|
if shm_size < 512 * 1024**2:
|
||||||
|
warn.append(
|
||||||
|
f" {YELLOW} [WARNING] Shared memory size might be too small, consider increasing it. {END}"
|
||||||
|
)
|
||||||
|
# Add additional warnings specific to your use case if needed.
|
||||||
|
return shm_hbytes, warn
|
||||||
|
except Exception as e:
|
||||||
|
return "UNKNOWN", [f"Error getting shared memory size: {e}"]
|
||||||
|
|
||||||
|
|
||||||
|
def human_readable_size(size):
|
||||||
|
units = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||||
|
i = 0
|
||||||
|
while size >= 1024 and i < len(units) - 1:
|
||||||
|
size /= 1024
|
||||||
|
i += 1
|
||||||
|
return f'{size:.2f} {units[i]}'
|
||||||
|
|
||||||
|
|
||||||
|
def debug_report():
|
||||||
|
max_dots = 33
|
||||||
|
|
||||||
|
report = [("torch install path", torch.__path__), ("torch version", torch.__version__),
|
||||||
|
("deepspeed install path", deepspeed.__path__),
|
||||||
|
("deepspeed info", f"{deepspeed.__version__}, {deepspeed.__git_hash__}, {deepspeed.__git_branch__}")]
|
||||||
|
if get_accelerator().device_name() == 'cuda':
|
||||||
|
hip_version = getattr(torch.version, "hip", None)
|
||||||
|
report.extend([("torch cuda version", torch.version.cuda), ("torch hip version", hip_version),
|
||||||
|
("nvcc version", (None if hip_version else nvcc_version())),
|
||||||
|
("deepspeed wheel compiled w.", f"torch {torch_info['version']}, " +
|
||||||
|
(f"hip {torch_info['hip_version']}" if hip_version else f"cuda {torch_info['cuda_version']}"))
|
||||||
|
])
|
||||||
|
else:
|
||||||
|
report.extend([("deepspeed wheel compiled w.", f"torch {torch_info['version']} ")])
|
||||||
|
|
||||||
|
report.append(("shared memory (/dev/shm) size", get_shm_size()))
|
||||||
|
|
||||||
|
print("DeepSpeed general environment info:")
|
||||||
|
for name, value in report:
|
||||||
|
warns = []
|
||||||
|
if isinstance(value, tuple):
|
||||||
|
value, warns = value
|
||||||
|
print(name, "." * (max_dots - len(name)), value)
|
||||||
|
if warns:
|
||||||
|
for warn in warns:
|
||||||
|
print(warn)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_arguments():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--hide_operator_status',
|
||||||
|
action='store_true',
|
||||||
|
help='Suppress display of installation and compatibility statuses of DeepSpeed operators. ')
|
||||||
|
parser.add_argument('--hide_errors_and_warnings', action='store_true', help='Suppress warning and error messages.')
|
||||||
|
args = parser.parse_args()
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def main(hide_operator_status=False, hide_errors_and_warnings=False):
|
||||||
|
if not hide_operator_status:
|
||||||
|
op_report(verbose=not hide_errors_and_warnings)
|
||||||
|
debug_report()
|
||||||
|
|
||||||
|
|
||||||
|
def cli_main():
|
||||||
|
args = parse_arguments()
|
||||||
|
main(hide_operator_status=args.hide_operator_status, hide_errors_and_warnings=args.hide_errors_and_warnings)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
These are the modified files you would need for a MANUAL build of DeepSpeed 11.1 or 11.2.
|
||||||
|
|
||||||
|
They were created by a mix of instructions from erew123 and S95Sedan.
|
||||||
|
|
||||||
|
|
||||||
|
- You still have to download the DeepSpeed v11.1 or v11.2 installation files from Microsoft to use these files.
|
||||||
|
|
||||||
|
https://github.com/microsoft/DeepSpeed/releases/tag/v0.11.2
|
||||||
|
|
||||||
|
|
||||||
|
- These files were provided by S95Sedan here:
|
||||||
|
|
||||||
|
https://github.com/S95Sedan/Deepspeed-Windows
|
||||||
|
|
||||||
|
|
||||||
|
- They are related to the manual build of DeepSpeed for AllTalk, which is linked here:
|
||||||
|
|
||||||
|
https://github.com/erew123/alltalk_tts/tree/main?tab=readme-ov-file#-option-2---a-bit-more-complicated
|
||||||
@@ -4,7 +4,7 @@ AllTalk is an updated version of the Coqui_tts extension for Text Generation web
|
|||||||
- **Custom Start-up Settings:** Adjust your default start-up settings. [Screenshot](https://github.com/erew123/alltalk_tts#screenshots)
|
- **Custom Start-up Settings:** Adjust your default start-up settings. [Screenshot](https://github.com/erew123/alltalk_tts#screenshots)
|
||||||
- **Narrarator:** Use different voices for main character and narration. [Example Narration](https://vocaroo.com/18fYWVxiQpk1)
|
- **Narrarator:** Use different voices for main character and narration. [Example Narration](https://vocaroo.com/18fYWVxiQpk1)
|
||||||
- **Low VRAM mode:** Improve generation performance if your VRAM is filled by your LLM. [Screenshot](https://github.com/erew123/alltalk_tts#screenshots)
|
- **Low VRAM mode:** Improve generation performance if your VRAM is filled by your LLM. [Screenshot](https://github.com/erew123/alltalk_tts#screenshots)
|
||||||
- **DeepSpeed:** When DeepSpeed is installed you can get a 3-4x performance boost generating TTS.
|
- **DeepSpeed:** A 3-4x performance boost generating TTS. [DeepSpeed Windows/Linux Instructions](https://github.com/erew123/alltalk_tts?tab=readme-ov-file#deepspeed-installation-options) [Screenshot](https://github.com/erew123/alltalk_tts/assets/35898566/548619c8-5f1b-47d0-a73d-54d2fee3f3db)
|
||||||
- **Local/Custom models:** Use any of the XTTSv2 models (API Local and XTTSv2 Local).
|
- **Local/Custom models:** Use any of the XTTSv2 models (API Local and XTTSv2 Local).
|
||||||
- **Optional wav file maintenance:** Configurable deletion of old output wav files. [Screenshot](https://github.com/erew123/alltalk_tts#screenshots)
|
- **Optional wav file maintenance:** Configurable deletion of old output wav files. [Screenshot](https://github.com/erew123/alltalk_tts#screenshots)
|
||||||
- **Documentation:** Fully documented with a built in webpage. [Screenshot](https://github.com/erew123/alltalk_tts#screenshots)
|
- **Documentation:** Fully documented with a built in webpage. [Screenshot](https://github.com/erew123/alltalk_tts#screenshots)
|
||||||
@@ -16,14 +16,16 @@ The latest build (13 Dec 2023) has had the entire text filtering engine and narr
|
|||||||
|
|
||||||
Should you want the older version of the narrator engine+text filtering, I will leave this older copy [here](https://github.com/erew123/alltalk_tts/releases/tag/v1-old-narrator)
|
Should you want the older version of the narrator engine+text filtering, I will leave this older copy [here](https://github.com/erew123/alltalk_tts/releases/tag/v1-old-narrator)
|
||||||
|
|
||||||
|
DeepSpeed **v11.2** can be installed within the **default text-generation-webui Python 3.11 environment**. Instructions [here](https://github.com/erew123/alltalk_tts#deepspeed-112-for-windows--python-311) (or scroll down). Please note, this is **not** an official Microsoft method (currently) so they will not support you with this style installation. Officially, only DeepSpeed v8.3 is installing on Python 3.9.x.
|
||||||
|
|
||||||
#### The one thing I cant easily work around
|
#### The one thing I cant easily work around
|
||||||
With a RP chat with your AI, on your character card `parameters menu` > `character tab` > `greeting` make sure that anything in there that is the narrator is in asterisks and anything spoken is in double quotes, then hit the `save` (disk) button. Greeting paragraphs/sentences are handled differently from how the AI sends text and so its difficut to account for them both.
|
With a RP chat with your AI, **on your character card** `parameters menu` > `character tab` > `greeting` make sure that anything in there that is the **narrator is in asterisks** and anything **spoken is in double quotes**, then hit the `save` (disk) button. Greeting paragraphs/sentences are handled differently from how the AI sends text and so its difficut to account for them both.
|
||||||
|
|
||||||
I could force a delimeter in at this stage, but I know it would/may affect things further down the line in the chat and I need a good think about that before just making a change. This issue **only** affects the greeting card/start of conversation and the "example" card that comes with text-generation-webui suffers this issue (if you want to try it for yourself). So you would put double quotes around like this (from the example card):
|
I could force a delimeter in at this stage, but I know it would/may affect things further down the line in the chat and I need a good think about that before just making a change. This issue **only** affects the greeting card/start of conversation and the "example" card that comes with text-generation-webui suffers this issue (if you want to try it for yourself). So you would put double quotes around like this (from the example card):
|
||||||
|
|
||||||
"Hey! I'm so excited to finally meet you. I've heard so many great things about you and I'm eager to pick your brain about computers. I'm sure you have a wealth of knowledge that I can learn from."
|
`"`Hey! I'm so excited to finally meet you. I've heard so many great things about you and I'm eager to pick your brain about computers. I'm sure you have a wealth of knowledge that I can learn from.`"`
|
||||||
|
|
||||||
## Installation on Text generation web UI
|
## 🟩 Installation on Text generation web UI
|
||||||
This has been tested on the current Dec 2023 release of Text generation webUI. If you have not updated it for a while, you may wish to update Text generation webUI, instructions [here](https://github.com/oobabooga/text-generation-webui#getting-updates)
|
This has been tested on the current Dec 2023 release of Text generation webUI. If you have not updated it for a while, you may wish to update Text generation webUI, instructions [here](https://github.com/oobabooga/text-generation-webui#getting-updates)
|
||||||
|
|
||||||
1) In a command prompt/terminal window you need to move into your Text generation webUI folder:
|
1) In a command prompt/terminal window you need to move into your Text generation webUI folder:
|
||||||
@@ -54,13 +56,17 @@ This has been tested on the current Dec 2023 release of Text generation webUI. I
|
|||||||
|
|
||||||
7) You can now start move back to the main Text generation webUI folder `cd ..` (a few times), start Text generation webUI (`start_windows.bat`,`./start_linux.sh`, `start_macos.sh` or `start_wsl.bat`) and load the AllTalk extension in the Text generation webUI **session** tab.
|
7) You can now start move back to the main Text generation webUI folder `cd ..` (a few times), start Text generation webUI (`start_windows.bat`,`./start_linux.sh`, `start_macos.sh` or `start_wsl.bat`) and load the AllTalk extension in the Text generation webUI **session** tab.
|
||||||
|
|
||||||
|
8) Please read the note below about start-up times and also the note above about ensuring your character cards are set up [correctly](https://github.com/erew123/alltalk_tts#the-one-thing-i-cant-easily-work-around)
|
||||||
|
|
||||||
|
9) Some extra voices downloadable [here](https://drive.google.com/file/d/1bYdZdr3L69kmzUN3vSiqZmLRD7-A3M47/view?usp=drive_link)
|
||||||
|
|
||||||
**Note: It can take a while to start up.** Check the command prompt/terminal window if you want to know what its doing. After it says "Model Loaded" the Text generation webUI is usually available on its IP address a few seconds later, for you to connect to in your browser.
|
**Note: It can take a while to start up.** Check the command prompt/terminal window if you want to know what its doing. After it says "Model Loaded" the Text generation webUI is usually available on its IP address a few seconds later, for you to connect to in your browser.
|
||||||
|
|
||||||
**Documentation:** Click on the link when inside Text generation webUI as shown in the screenshot [here](https://github.com/erew123/alltalk_tts#screenshots)
|
**Documentation:** Click on the link when inside Text generation webUI as shown in the screenshot [here](https://github.com/erew123/alltalk_tts#screenshots)
|
||||||
|
|
||||||
**Where to find voices** https://aiartes.com/voiceai or https://commons.wikimedia.org/ or interviews on youtube etc. Instructions on how to cut down and prepare a voice sample are within the built in documentation.
|
**Where to find voices** https://aiartes.com/voiceai or https://commons.wikimedia.org/ or interviews on youtube etc. Instructions on how to cut down and prepare a voice sample are within the built in documentation.
|
||||||
|
|
||||||
### Other installation notes
|
### 🟩 Other installation notes
|
||||||
On first startup, AllTalk will download the Coqui XTTSv2 2.0.2 model to its **models** folder (1.8GB space required). You can customse your model or use the TTS latest model within the interface (details in documentation).
|
On first startup, AllTalk will download the Coqui XTTSv2 2.0.2 model to its **models** folder (1.8GB space required). You can customse your model or use the TTS latest model within the interface (details in documentation).
|
||||||
|
|
||||||
Once the extension is loaded, please find all documentation and settings on the link provided in the interface (as shown in the screenshot below).
|
Once the extension is loaded, please find all documentation and settings on the link provided in the interface (as shown in the screenshot below).
|
||||||
@@ -68,5 +74,130 @@ Once the extension is loaded, please find all documentation and settings on the
|
|||||||
To start AllTalk every Text generation webUI loads, edit the Text generation webUI `CMD_FLAGS.txt` file in the main `text-generation-webui` folder and add `--extensions alltalk_tts`.
|
To start AllTalk every Text generation webUI loads, edit the Text generation webUI `CMD_FLAGS.txt` file in the main `text-generation-webui` folder and add `--extensions alltalk_tts`.
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
| |  |
|
| |  |
|
||||||
|:---:|:---:|
|
|:---:|:---:|
|
||||||
|
| |  |
|
||||||
|
|
||||||
|
## DeepSpeed Installation Options
|
||||||
|
|
||||||
|
### 🔵 For Linux
|
||||||
|
Covered in the online/buit-in documentation, but a nice easy install.
|
||||||
|
|
||||||
|
### 🟢🟡 For Windows & Python 3.11
|
||||||
|
DeepSpeed v11.1 and v11.2 will work on the current text-generation-webui Python 3.11 environment! You have 2x options for how to setup DeepSpeed on Windows. A quick way (🟢Option 1) and a long way (🟡Option 2).
|
||||||
|
|
||||||
|
Thanks to [@S95Sedan](https://github.com/S95Sedan) - They managed to get DeepSpeed 11.2 working on Windows via making some edits to the original Microsoft DeepSpeed v11.2 installation. The original post is [here](https://github.com/oobabooga/text-generation-webui/issues/4734#issuecomment-1843984142).
|
||||||
|
|
||||||
|
#### 🟢 OPTION 1 - Quick and easy!
|
||||||
|
#### Pre-Compiled Wheel Deepspeed v11.1 (for Windows and Python 3.11)
|
||||||
|
[@S95Sedan](https://github.com/S95Sedan) has kindly provided a pre-compiled DeepSpeed v11.1 wheel file, which you can download and use. To use this, you will need to:
|
||||||
|
|
||||||
|
**Note:** In my tests, with this method you will **not** need to install the Nvidia CUDA toolkit to make this work, but AllTalk may warn you when starting DeepSpeed that it doesnt see the CUDA Toolkit, however, it works fine for TTS purposes.
|
||||||
|
|
||||||
|
1) Download the file [deepspeed-0.11.1+e9503fe-cp311-cp311-win_amd64.whl](https://drive.google.com/file/d/1PFsf6uSPY5Cb4o9VxiZ7DLv-j35L7Y41/view?usp=sharing) by going to the link and clicking the **download** icon at the top right of the screen and save the file it inside your **text-generation-webui** folder.
|
||||||
|
|
||||||
|
2) Open a command prompt window, move into your **text-generation-webui folder**, you can now start the Python environment for text-generation-webui:
|
||||||
|
|
||||||
|
`cmd_windows.bat`
|
||||||
|
|
||||||
|
3) With the file that you saved in the **text-generation-webui folder** you now type the following:
|
||||||
|
|
||||||
|
`pip install "deepspeed-0.11.1+e9503fe-cp311-cp311-win_amd64.whl"`
|
||||||
|
|
||||||
|
4) This should install through cleanly and you should now have DeepSpeed v11.1 installed within the Python 3.11 environment of text-generation-webui.
|
||||||
|
|
||||||
|
5) When you start up text-generation-webui, and AllTalk starts, you should see **[AllTalk Startup] DeepSpeed Detected**
|
||||||
|
|
||||||
|
6) Within AllTalk, you will now have a checkbox for **Activate DeepSpeed** though remember you can only change **1x setting every 15 or so seconds**, so dont try to activate DeepSpeed **and** LowVRAM/Change your model simultantiously. Do one of those, wait 15-20 seconds until the change is confirmed in the terminal/command prompt, then you can change the other. When you are happy it works, you can set the default start-up settings in the settings page.
|
||||||
|
|
||||||
|
#### 🟡 OPTION 2 - A bit more complicated!
|
||||||
|
|
||||||
|
#### Manual Build DeepSpeed v11.2 (for Windows and Python 3.11)
|
||||||
|
DeepSpeed Version 11.2 with CUDA 12.1 - Installation Instructions:
|
||||||
|
|
||||||
|
1. Download the 11.2 release of [DeepSpeed](https://github.com/microsoft/DeepSpeed/releases/tag/v0.11.2) extract it to a folder.
|
||||||
|
2. Install Visual C++ build tools, such as [VS2019 C++ x64/x86](https://learn.microsoft.com/en-us/visualstudio/releases/2019/redistribution#vs2019-download) build tools.
|
||||||
|
3. Download and install the [Nvidia Cuda Toolkit 12.1](https://developer.nvidia.com/cuda-12-1-0-download-archive)
|
||||||
|
4. Edit your Windows environment variables to ensure that CUDA_HOME and CUDA_PATH are set to your Nvidia Cuda Toolkit path. (The folder above the bin folder that nvcc.exe is installed in). Examples are:<br>
|
||||||
|
```set CUDA_HOME=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1```<br>
|
||||||
|
```set CUDA_PATH=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1```<br>
|
||||||
|
|
||||||
|
5. OPTIONAL If you do not have an python environment already created, you can install [Miniconda](https://docs.conda.io/projects/miniconda/en/latest/miniconda-install.html), then at a command prompt, create and activate your environment with:<br>
|
||||||
|
```conda create -n pythonenv python=3.11```<br>
|
||||||
|
```activate pythonenv```<br>
|
||||||
|
|
||||||
|
6. Launch the Command Prompt cmd with Administrator privilege as it requires admin to allow creating symlink folders.
|
||||||
|
7. Install PyTorch, 2.1.0 with CUDA 12.1 into your Python 3.11 environment e.g:<br>
|
||||||
|
```activate pythonenv``` (activate your python environment)<br>
|
||||||
|
```conda install pytorch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 pytorch-cuda=12.1 -c pytorch -c nvidia```
|
||||||
|
|
||||||
|
8. In your python environment check that your CUDA_HOME and CUDA_PATH are still pointing to the correct location.<br>
|
||||||
|
```set``` (to list and check the windows environment variables. Refer to step 4 if not)
|
||||||
|
|
||||||
|
9. Navigate to your deepspeed folder in the Command Prompt:<br>
|
||||||
|
```cd c:\deepspeed``` (wherever you extracted it to)
|
||||||
|
|
||||||
|
10. Modify the following files:<br>
|
||||||
|
|
||||||
|
**(These modified files are included in the git-pull of AllTalk, but if you want to modify them yourself, please follow the below)**
|
||||||
|
|
||||||
|
deepspeed-0.11.2/build_win.bat** - at the top of the file, add:<br>
|
||||||
|
```set DS_BUILD_EVOFORMER_ATTN=0```
|
||||||
|
|
||||||
|
deepspeed-0.11.2/csrc/quantization/pt_binding.cpp - lines 244-250 - change to:
|
||||||
|
```
|
||||||
|
std::vector<int64_t> sz_vector(input_vals.sizes().begin(), input_vals.sizes().end());
|
||||||
|
sz_vector[sz_vector.size() - 1] = sz_vector.back() / devices_per_node; // num of GPU per nodes
|
||||||
|
at::IntArrayRef sz(sz_vector);
|
||||||
|
auto output = torch::empty(sz, output_options);
|
||||||
|
|
||||||
|
const int elems_per_in_tensor = at::numel(input_vals) / devices_per_node;
|
||||||
|
const int elems_per_in_group = elems_per_in_tensor / (in_groups / devices_per_node);
|
||||||
|
const int elems_per_out_group = elems_per_in_tensor / out_groups;
|
||||||
|
```
|
||||||
|
|
||||||
|
deepspeed-0.11.2/csrc/transformer/inference/csrc/pt_binding.cpp
|
||||||
|
lines 541-542 - change to:
|
||||||
|
```
|
||||||
|
{static_cast<unsigned>(hidden_dim * InferenceContext::Instance().GetMaxTokenLength()),
|
||||||
|
static_cast<unsigned>(k * InferenceContext::Instance().GetMaxTokenLength()),
|
||||||
|
```
|
||||||
|
|
||||||
|
lines 550-551 - change to:
|
||||||
|
```
|
||||||
|
{static_cast<unsigned>(hidden_dim * InferenceContext::Instance().GetMaxTokenLength()),
|
||||||
|
static_cast<unsigned>(k * InferenceContext::Instance().GetMaxTokenLength()),
|
||||||
|
```
|
||||||
|
line 1581 - change to:
|
||||||
|
```
|
||||||
|
at::from_blob(intermediate_ptr, {input.size(0), input.size(1), static_cast<int64_t>(mlp_1_out_neurons)}, options);
|
||||||
|
```
|
||||||
|
|
||||||
|
deepspeed-0.11.2/deepspeed/env_report.py
|
||||||
|
line 10 - add:
|
||||||
|
```
|
||||||
|
import psutil
|
||||||
|
```
|
||||||
|
line 83 - 100 - change to:
|
||||||
|
```
|
||||||
|
def get_shm_size():
|
||||||
|
try:
|
||||||
|
temp_dir = os.getenv('TEMP') or os.getenv('TMP') or os.path.join(os.path.expanduser('~'), 'tmp')
|
||||||
|
shm_stats = psutil.disk_usage(temp_dir)
|
||||||
|
shm_size = shm_stats.total
|
||||||
|
shm_hbytes = human_readable_size(shm_size)
|
||||||
|
warn = []
|
||||||
|
if shm_size < 512 * 1024**2:
|
||||||
|
warn.append(
|
||||||
|
f" {YELLOW} [WARNING] Shared memory size might be too small, consider increasing it. {END}"
|
||||||
|
)
|
||||||
|
# Add additional warnings specific to your use case if needed.
|
||||||
|
return shm_hbytes, warn
|
||||||
|
except Exception as e:
|
||||||
|
return "UNKNOWN", [f"Error getting shared memory size: {e}"]
|
||||||
|
```
|
||||||
|
|
||||||
|
11. While still in your command line with python environment enabled run:<br>
|
||||||
|
```build_win.bat```
|
||||||
|
|
||||||
|
12. Now cd dist to go into your dist folder and you can now pip install deepspeed-YOURFILENAME.whl (or whatever your WHL file is called).
|
||||||
@@ -271,7 +271,6 @@ else:
|
|||||||
# Cleanly kill off this script, but allow text-generation-webui to keep running, albeit without this alltalk_tts
|
# Cleanly kill off this script, but allow text-generation-webui to keep running, albeit without this alltalk_tts
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
#### MODEL LOADING AND UNLOADING ####
|
#### MODEL LOADING AND UNLOADING ####
|
||||||
#####################################
|
#####################################
|
||||||
@@ -294,16 +293,19 @@ def send_reload_request(tts_method):
|
|||||||
params["tts_method_xtts_local"] = False
|
params["tts_method_xtts_local"] = False
|
||||||
params["tts_method_api_tts"] = True
|
params["tts_method_api_tts"] = True
|
||||||
params["deepspeed_activate"] = False
|
params["deepspeed_activate"] = False
|
||||||
|
audio_path = this_dir / "templates" / "apitts.wav"
|
||||||
elif tts_method == "API Local":
|
elif tts_method == "API Local":
|
||||||
params["tts_method_api_tts"] = False
|
params["tts_method_api_tts"] = False
|
||||||
params["tts_method_xtts_local"] = False
|
params["tts_method_xtts_local"] = False
|
||||||
params["tts_method_api_local"] = True
|
params["tts_method_api_local"] = True
|
||||||
params["deepspeed_activate"] = False
|
params["deepspeed_activate"] = False
|
||||||
|
audio_path = this_dir / "templates" / "apilocal.wav"
|
||||||
elif tts_method == "XTTSv2 Local":
|
elif tts_method == "XTTSv2 Local":
|
||||||
params["tts_method_api_tts"] = False
|
params["tts_method_api_tts"] = False
|
||||||
params["tts_method_api_local"] = False
|
params["tts_method_api_local"] = False
|
||||||
params["tts_method_xtts_local"] = True
|
params["tts_method_xtts_local"] = True
|
||||||
return json_response
|
audio_path = this_dir / "templates" / "xttslocal.wav"
|
||||||
|
return f'<audio src="file/{audio_path}" controls autoplay></audio>'
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
# Handle the HTTP request error
|
# Handle the HTTP request error
|
||||||
print(
|
print(
|
||||||
@@ -311,7 +313,6 @@ def send_reload_request(tts_method):
|
|||||||
)
|
)
|
||||||
return {"status": "error", "message": str(e)}
|
return {"status": "error", "message": str(e)}
|
||||||
|
|
||||||
|
|
||||||
##################
|
##################
|
||||||
#### LOW VRAM ####
|
#### LOW VRAM ####
|
||||||
##################
|
##################
|
||||||
@@ -319,6 +320,10 @@ def send_reload_request(tts_method):
|
|||||||
def send_lowvram_request(low_vram):
|
def send_lowvram_request(low_vram):
|
||||||
try:
|
try:
|
||||||
params["model_loaded"] = False
|
params["model_loaded"] = False
|
||||||
|
if low_vram:
|
||||||
|
audio_path = this_dir / "templates" / "lowvramenabled.wav"
|
||||||
|
else:
|
||||||
|
audio_path = this_dir / "templates" / "lowvramdisabled.wav"
|
||||||
url = f"{base_url}/api/lowvramsetting?new_low_vram_value={low_vram}"
|
url = f"{base_url}/api/lowvramsetting?new_low_vram_value={low_vram}"
|
||||||
headers = {"Content-Type": "application/json"}
|
headers = {"Content-Type": "application/json"}
|
||||||
response = requests.post(url, headers=headers)
|
response = requests.post(url, headers=headers)
|
||||||
@@ -328,7 +333,7 @@ def send_lowvram_request(low_vram):
|
|||||||
if json_response.get("status") == "lowvram-success":
|
if json_response.get("status") == "lowvram-success":
|
||||||
# Update any relevant variables or perform other actions on success
|
# Update any relevant variables or perform other actions on success
|
||||||
params["model_loaded"] = True
|
params["model_loaded"] = True
|
||||||
return json_response
|
return f'<audio src="file/{audio_path}" controls autoplay></audio>'
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
# Handle the HTTP request error
|
# Handle the HTTP request error
|
||||||
print(
|
print(
|
||||||
@@ -344,6 +349,11 @@ def send_lowvram_request(low_vram):
|
|||||||
def send_deepspeed_request(deepspeed_param):
|
def send_deepspeed_request(deepspeed_param):
|
||||||
try:
|
try:
|
||||||
params["model_loaded"] = False
|
params["model_loaded"] = False
|
||||||
|
if deepspeed_param:
|
||||||
|
audio_path = this_dir / "templates" / "deepspeedenabled.wav"
|
||||||
|
else:
|
||||||
|
audio_path = this_dir / "templates" / "deepspeeddisabled.wav"
|
||||||
|
|
||||||
url = f"{base_url}/api/deepspeed?new_deepspeed_value={deepspeed_param}"
|
url = f"{base_url}/api/deepspeed?new_deepspeed_value={deepspeed_param}"
|
||||||
headers = {"Content-Type": "application/json"}
|
headers = {"Content-Type": "application/json"}
|
||||||
response = requests.post(url, headers=headers)
|
response = requests.post(url, headers=headers)
|
||||||
@@ -353,7 +363,7 @@ def send_deepspeed_request(deepspeed_param):
|
|||||||
if json_response.get("status") == "deepspeed-success":
|
if json_response.get("status") == "deepspeed-success":
|
||||||
# Update any relevant variables or perform other actions on success
|
# Update any relevant variables or perform other actions on success
|
||||||
params["model_loaded"] = True
|
params["model_loaded"] = True
|
||||||
return json_response
|
return f'<audio src="file/{audio_path}" controls autoplay></audio>'
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
# Handle the HTTP request error
|
# Handle the HTTP request error
|
||||||
print(
|
print(
|
||||||
@@ -490,6 +500,7 @@ def output_modifier(string, state):
|
|||||||
if process_lock.acquire(blocking=False):
|
if process_lock.acquire(blocking=False):
|
||||||
try:
|
try:
|
||||||
if params["narrator_enabled"]:
|
if params["narrator_enabled"]:
|
||||||
|
# print(original_string)
|
||||||
# Do Some basic stripping and remove any double CR's
|
# Do Some basic stripping and remove any double CR's
|
||||||
processed_string = (
|
processed_string = (
|
||||||
original_string
|
original_string
|
||||||
@@ -510,8 +521,11 @@ def output_modifier(string, state):
|
|||||||
.replace('"', '"<')
|
.replace('"', '"<')
|
||||||
)
|
)
|
||||||
#capturing another outlier in inital character paragraph
|
#capturing another outlier in inital character paragraph
|
||||||
|
# print("processed string 1 is:", processed_string)
|
||||||
processed_string = processed_string.replace('"<. *', '"< *"')
|
processed_string = processed_string.replace('"<. *', '"< *"')
|
||||||
processed_string = processed_string.replace('< *"', '< *')
|
processed_string = processed_string.replace('< *"', '< *')
|
||||||
|
processed_string = processed_string.replace('. *', '< *')
|
||||||
|
# print("processed string 2 is:", processed_string)
|
||||||
# Set up a tracking of the individual wav files.
|
# Set up a tracking of the individual wav files.
|
||||||
audio_files_all_paragraphs = []
|
audio_files_all_paragraphs = []
|
||||||
# Split the line using " and ".* " (so end of sentences, leaving special characters added to the start of all OTHER sentences, bar possibly the first one if its starting with a *
|
# Split the line using " and ".* " (so end of sentences, leaving special characters added to the start of all OTHER sentences, bar possibly the first one if its starting with a *
|
||||||
@@ -526,7 +540,7 @@ def output_modifier(string, state):
|
|||||||
if '<' in part and '< *' not in part and '<*' not in part and '< *' not in part and '< ' not in part and '< ' not in part:
|
if '<' in part and '< *' not in part and '<*' not in part and '< *' not in part and '< ' not in part and '< ' not in part:
|
||||||
cleaned_part = html.unescape(part.replace('<', ''))
|
cleaned_part = html.unescape(part.replace('<', ''))
|
||||||
voice_to_use = params["voice"]
|
voice_to_use = params["voice"]
|
||||||
#Narrator will always be am * or < with an * a position or two after it.
|
#Narrator will always be an * or < with an * a position or two after it.
|
||||||
elif '<*' in part or '< *' in part or '< *' in part or '*' in part:
|
elif '<*' in part or '< *' in part or '< *' in part or '*' in part:
|
||||||
cleaned_part = html.unescape(part.replace('<*', '').replace('< *', '').replace('< *', '').replace('*', ''))
|
cleaned_part = html.unescape(part.replace('<*', '').replace('< *', '').replace('< *', '').replace('*', ''))
|
||||||
voice_to_use = params["narrator_voice"]
|
voice_to_use = params["narrator_voice"]
|
||||||
@@ -651,7 +665,6 @@ def state_modifier(state):
|
|||||||
state["stream"] = False
|
state["stream"] = False
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
|
||||||
def update_narrator_enabled(value):
|
def update_narrator_enabled(value):
|
||||||
if value == "Enabled":
|
if value == "Enabled":
|
||||||
params["narrator_enabled"] = True
|
params["narrator_enabled"] = True
|
||||||
@@ -672,7 +685,6 @@ def input_modifier(string, state):
|
|||||||
shared.processing_message = "*Is recording a voice message...*"
|
shared.processing_message = "*Is recording a voice message...*"
|
||||||
return string
|
return string
|
||||||
|
|
||||||
|
|
||||||
def custom_css():
|
def custom_css():
|
||||||
path_to_css = Path(f"{this_dir}/style.css")
|
path_to_css = Path(f"{this_dir}/style.css")
|
||||||
return open(path_to_css, "r").read()
|
return open(path_to_css, "r").read()
|
||||||
@@ -761,11 +773,13 @@ def ui():
|
|||||||
low_vram = gr.Checkbox(
|
low_vram = gr.Checkbox(
|
||||||
value=params["low_vram"], label="Low VRAM mode (Read NOTE)"
|
value=params["low_vram"], label="Low VRAM mode (Read NOTE)"
|
||||||
)
|
)
|
||||||
|
low_vram_play = gr.HTML(visible=False)
|
||||||
deepspeed_checkbox = gr.Checkbox(
|
deepspeed_checkbox = gr.Checkbox(
|
||||||
value=params["deepspeed_activate"],
|
value=params["deepspeed_activate"],
|
||||||
label="Activate DeepSpeed (Read NOTE)",
|
label="Activate DeepSpeed (Read NOTE)",
|
||||||
visible=deepspeed_installed,
|
visible=deepspeed_installed,
|
||||||
)
|
)
|
||||||
|
deepspeed_checkbox_play = gr.HTML(visible=False)
|
||||||
|
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
tts_radio_buttons = gr.Radio(
|
tts_radio_buttons = gr.Radio(
|
||||||
@@ -773,6 +787,7 @@ def ui():
|
|||||||
label="Select TTS Generation Method (Read NOTE)",
|
label="Select TTS Generation Method (Read NOTE)",
|
||||||
value=gr_modelchoice, # Set the default value
|
value=gr_modelchoice, # Set the default value
|
||||||
)
|
)
|
||||||
|
tts_radio_buttons_play = gr.HTML(visible=False)
|
||||||
explanation_text = gr.HTML(
|
explanation_text = gr.HTML(
|
||||||
f"<p>NOTE: Switching Model Type, Low VRAM & DeepSpeed takes 15 seconds. Each TTS generation method has a slightly different sound. DeepSpeed checkbox is only visible if DeepSpeed is present. Readme & Settings: <a href='http://{params['ip_address']}:{params['port_number']}'>http://{params['ip_address']}:{params['port_number']}</a>"
|
f"<p>NOTE: Switching Model Type, Low VRAM & DeepSpeed takes 15 seconds. Each TTS generation method has a slightly different sound. DeepSpeed checkbox is only visible if DeepSpeed is present. Readme & Settings: <a href='http://{params['ip_address']}:{params['port_number']}'>http://{params['ip_address']}:{params['port_number']}</a>"
|
||||||
)
|
)
|
||||||
@@ -845,9 +860,9 @@ def ui():
|
|||||||
activate.change(lambda x: params.update({"activate": x}), activate, None)
|
activate.change(lambda x: params.update({"activate": x}), activate, None)
|
||||||
autoplay.change(lambda x: params.update({"autoplay": x}), autoplay, None)
|
autoplay.change(lambda x: params.update({"autoplay": x}), autoplay, None)
|
||||||
low_vram.change(lambda x: params.update({"low_vram": x}), low_vram, None)
|
low_vram.change(lambda x: params.update({"low_vram": x}), low_vram, None)
|
||||||
low_vram.change(lambda x: send_lowvram_request(x), low_vram, None)
|
low_vram.change(lambda x: send_lowvram_request(x), low_vram, low_vram_play, None)
|
||||||
tts_radio_buttons.change(send_reload_request, tts_radio_buttons, None)
|
tts_radio_buttons.change(send_reload_request, tts_radio_buttons, tts_radio_buttons_play, None)
|
||||||
deepspeed_checkbox.change(send_deepspeed_request, deepspeed_checkbox, None)
|
deepspeed_checkbox.change(send_deepspeed_request, deepspeed_checkbox, deepspeed_checkbox_play, None)
|
||||||
remove_trailing_dots.change(
|
remove_trailing_dots.change(
|
||||||
lambda x: params.update({"remove_trailing_dots": x}), remove_trailing_dots, None
|
lambda x: params.update({"remove_trailing_dots": x}), remove_trailing_dots, None
|
||||||
)
|
)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 476 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 547 KiB |
Binary file not shown.
+190
-59
@@ -17,7 +17,7 @@ from fastapi import (
|
|||||||
Response,
|
Response,
|
||||||
Depends,
|
Depends,
|
||||||
)
|
)
|
||||||
from fastapi.responses import JSONResponse, HTMLResponse, RedirectResponse
|
from fastapi.responses import JSONResponse, HTMLResponse, RedirectResponse, FileResponse
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
@@ -186,9 +186,7 @@ async def api_manual_load_model():
|
|||||||
)
|
)
|
||||||
model = TTS(
|
model = TTS(
|
||||||
model_path=modeldownload_base_path / modeldownload_model_path,
|
model_path=modeldownload_base_path / modeldownload_model_path,
|
||||||
config_path=modeldownload_base_path
|
config_path=modeldownload_base_path / modeldownload_model_path / "config.json",
|
||||||
/ modeldownload_model_path
|
|
||||||
/ "config.json",
|
|
||||||
).to(device)
|
).to(device)
|
||||||
return model
|
return model
|
||||||
|
|
||||||
@@ -200,6 +198,7 @@ async def xtts_manual_load_model():
|
|||||||
# check to see if a custom path has been set in modeldownload.json and use that path to load the model if so
|
# check to see if a custom path has been set in modeldownload.json and use that path to load the model if so
|
||||||
if str(modeldownload_base_path) == "models":
|
if str(modeldownload_base_path) == "models":
|
||||||
config_path = this_dir / "models" / modeldownload_model_path / "config.json"
|
config_path = this_dir / "models" / modeldownload_model_path / "config.json"
|
||||||
|
vocab_path_dir = this_dir / "models" / modeldownload_model_path / "vocab.json"
|
||||||
checkpoint_dir = this_dir / "models" / modeldownload_model_path
|
checkpoint_dir = this_dir / "models" / modeldownload_model_path
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
@@ -207,12 +206,14 @@ async def xtts_manual_load_model():
|
|||||||
modeldownload_base_path / modeldownload_model_path,
|
modeldownload_base_path / modeldownload_model_path,
|
||||||
)
|
)
|
||||||
config_path = modeldownload_base_path / modeldownload_model_path / "config.json"
|
config_path = modeldownload_base_path / modeldownload_model_path / "config.json"
|
||||||
|
vocab_path_dir = modeldownload_base_path / modeldownload_model_path / "vocab.json"
|
||||||
checkpoint_dir = modeldownload_base_path / modeldownload_model_path
|
checkpoint_dir = modeldownload_base_path / modeldownload_model_path
|
||||||
config.load_json(str(config_path))
|
config.load_json(str(config_path))
|
||||||
model = Xtts.init_from_config(config)
|
model = Xtts.init_from_config(config)
|
||||||
model.load_checkpoint(
|
model.load_checkpoint(
|
||||||
config,
|
config,
|
||||||
checkpoint_dir=str(checkpoint_dir),
|
checkpoint_dir=str(checkpoint_dir),
|
||||||
|
vocab_path=str(vocab_path_dir),
|
||||||
use_deepspeed=params["deepspeed_activate"],
|
use_deepspeed=params["deepspeed_activate"],
|
||||||
)
|
)
|
||||||
model.to(device)
|
model.to(device)
|
||||||
@@ -538,6 +539,7 @@ async def get_settings(request: Request):
|
|||||||
"wav_files": wav_files,
|
"wav_files": wav_files,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# Define an endpoint to serve static files
|
# Define an endpoint to serve static files
|
||||||
app.mount("/static", StaticFiles(directory=str(this_dir / "templates")), name="static")
|
app.mount("/static", StaticFiles(directory=str(this_dir / "templates")), name="static")
|
||||||
|
|
||||||
@@ -596,6 +598,25 @@ async def update_settings(
|
|||||||
return RedirectResponse(url="/settings", status_code=303)
|
return RedirectResponse(url="/settings", status_code=303)
|
||||||
|
|
||||||
|
|
||||||
|
##################################
|
||||||
|
#### SETTINGS PAGE DEMO VOICE ####
|
||||||
|
##################################
|
||||||
|
# Submit demo post here
|
||||||
|
@app.post("/tts-demo-request", response_class=JSONResponse)
|
||||||
|
async def tts_demo_request(request: Request, text: str = Form(...), voice: str = Form(...), language: str = Form(...), output_file: str = Form(...)):
|
||||||
|
try:
|
||||||
|
output_file_path = this_dir / "outputs" / output_file
|
||||||
|
await generate_audio(text, voice, language, output_file_path)
|
||||||
|
return JSONResponse(content={"output_file_path": str(output_file)}, status_code=200)
|
||||||
|
except Exception as e:
|
||||||
|
return JSONResponse(content={"error": "An error occurred"}, status_code=500)
|
||||||
|
|
||||||
|
# Gives web access to the output files
|
||||||
|
@app.get("/audio/{filename}")
|
||||||
|
async def get_audio(filename: str):
|
||||||
|
audio_path = this_dir / "outputs" / filename
|
||||||
|
return FileResponse(audio_path)
|
||||||
|
|
||||||
#############################################################
|
#############################################################
|
||||||
#### DOCUMENTATION - README ETC - PRESENTED AS A WEBPAGE ####
|
#### DOCUMENTATION - README ETC - PRESENTED AS A WEBPAGE ####
|
||||||
#############################################################
|
#############################################################
|
||||||
@@ -697,6 +718,64 @@ simple_webpage = """
|
|||||||
.option-b {
|
.option-b {
|
||||||
color: red;
|
color: red;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* New styles for TTS Request Page */
|
||||||
|
#container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 50px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea, input, select, button {
|
||||||
|
padding: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: #4caf50;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#outputFilePath {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#audioSource {
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#outputFilePath {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@@ -704,8 +783,8 @@ simple_webpage = """
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1 id="toc">AllTalk TTS for Text generation webUI</h1>
|
<h1 id="toc">AllTalk TTS for Text generation webUI</h1>
|
||||||
<p>If you are looking for your <b>Text generation webUI</b> webpage, try visiting <a href="http://127.0.0.1:7860" target="_blank">http://127.0.0.1:7860</a>.</p>
|
<p><b>Text generation webUI</b> webpage <a href="http://127.0.0.1:7860" target="_blank">here</a> and documentation <a href="https://github.com/oobabooga/text-generation-webui/wiki" target="_blank">here</a></p>
|
||||||
<p><b>Text generation webUI</b> documentation and wiki <a href="https://github.com/oobabooga/text-generation-webui/wiki" target="_blank">https://github.com/oobabooga/text-generation-webui/wiki</a>.</p>
|
<p><b>AllTalk Github</b> <a href="https://github.com/erew123/alltalk_tts" target="_blank">here</a>
|
||||||
|
|
||||||
<iframe src="http://127.0.0.1:7851/settings" width="100%" height="500" frameborder="0" style="margin: 0; padding: 0;"></iframe>
|
<iframe src="http://127.0.0.1:7851/settings" width="100%" height="500" frameborder="0" style="margin: 0; padding: 0;"></iframe>
|
||||||
|
|
||||||
@@ -723,6 +802,7 @@ simple_webpage = """
|
|||||||
<li><a href="#other-features">Other Features of AllTalk_TTS Extension for Text generation webUI</a></li>
|
<li><a href="#other-features">Other Features of AllTalk_TTS Extension for Text generation webUI</a></li>
|
||||||
<li><a href="#TTSmodels">TTS Models/Methods</a></li>
|
<li><a href="#TTSmodels">TTS Models/Methods</a></li>
|
||||||
<li><a href="#customTTSmodels">Custom TTS Models and Model path</a></li>
|
<li><a href="#customTTSmodels">Custom TTS Models and Model path</a></li>
|
||||||
|
<li><a href="#demotesttts">Demo/Test TTS output</a></li>
|
||||||
<li><a href="#curl-commands">CURL Commands</a></li>
|
<li><a href="#curl-commands">CURL Commands</a></li>
|
||||||
<li><a href="#configuration-details">Configuration Details</a></li>
|
<li><a href="#configuration-details">Configuration Details</a></li>
|
||||||
<li><a href="#debugging-and-tts-generation-information">Debugging and TTS Generation Information</a></li>
|
<li><a href="#debugging-and-tts-generation-information">Debugging and TTS Generation Information</a></li>
|
||||||
@@ -840,13 +920,20 @@ simple_webpage = """
|
|||||||
|
|
||||||
<h3 id="low-vram-option-overview"><strong>Low VRAM Overview:</strong></h3>
|
<h3 id="low-vram-option-overview"><strong>Low VRAM Overview:</strong></h3>
|
||||||
<p>The Low VRAM option is a crucial feature designed to enhance performance under constrained Video Random Access Memory (VRAM) conditions, as the TTS models require 2GB-3GB of VRAM to run effectively. This feature strategically manages the relocation of the Text-to-Speech (TTS) model between your system's Random Access Memory (RAM) and VRAM, moving it between the two on the fly.</p>
|
<p>The Low VRAM option is a crucial feature designed to enhance performance under constrained Video Random Access Memory (VRAM) conditions, as the TTS models require 2GB-3GB of VRAM to run effectively. This feature strategically manages the relocation of the Text-to-Speech (TTS) model between your system's Random Access Memory (RAM) and VRAM, moving it between the two on the fly.</p>
|
||||||
|
<p>When you dont have enough VRAM free after loading your LLM model into your VRAM (Normal Mode example below), you can see that with so little working space, your GPU will have to swap in and out bits of the TTS model, which causes horrible slowdown.</p>
|
||||||
|
|
||||||
<p><b>Note: </b>An Nvidia Graphics card is required for LowVRAM, as you will be using system memory for the models otherwise.</p>
|
<p><b>Note: </b>An Nvidia Graphics card is required for LowVRAM, as you will be using system memory for the models otherwise.</p>
|
||||||
|
|
||||||
<h4>How It Works:</h4>
|
<h4>How It Works:</h4>
|
||||||
<p>The Low VRAM option intelligently orchestrates the relocation of the entire TTS model. When the TTS engine requires VRAM for processing, the entire model seamlessly moves into VRAM, causing your LLM to unload/displace some layers, ensuring optimal performance of the TTS engine.</p>
|
<p>The Low VRAM mode intelligently orchestrates the relocation of the entire TTS model. When the TTS engine requires VRAM for processing, the entire model seamlessly moves into VRAM, causing your LLM to unload/displace some layers, ensuring optimal performance of the TTS engine.</p>
|
||||||
<p>The TTS model is fully loaded into VRAM, facilitating uninterrupted and efficient TTS generation, creating contiguous space for the TTS model and significantly accelerating TTS processing, especially for long paragraphs. Post-TTS processing, the model promptly moves back to RAM, freeing up VRAM space for your Language Model (LLM) to load back in the missing layers. This adds about 1-2 seconds to both text generation by the LLM and the TTS engine.</p>
|
<p>The TTS model is fully loaded into VRAM, facilitating uninterrupted and efficient TTS generation, creating contiguous space for the TTS model and significantly accelerating TTS processing, especially for long paragraphs. Post-TTS processing, the model promptly moves back to RAM, freeing up VRAM space for your Language Model (LLM) to load back in the missing layers. This adds about 1-2 seconds to both text generation by the LLM and the TTS engine.</p>
|
||||||
<p>By transferring the entire model between RAM and VRAM, the Low VRAM option avoids fragmentation, ensuring the TTS model remains cohesive and accessible.</p>
|
<p>By transferring the entire model between RAM and VRAM, the Low VRAM option avoids fragmentation, ensuring the TTS model remains cohesive and accessible.</p>
|
||||||
<p>This creates a TTS generation performance Boost for Low VRAM Users and is particularly beneficial for users with less than 2GB of free VRAM after loading their LLM, delivering a substantial 5-10x improvement in TTS generation speed.</p>
|
<p>This creates a TTS generation performance Boost for Low VRAM Users and is particularly beneficial for users with less than 2GB of free VRAM after loading their LLM, delivering a substantial 5-10x improvement in TTS generation speed.</p>
|
||||||
|
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<img src="/static/lowvrammode.png" alt="How Low VRAM Works">
|
||||||
|
</div>
|
||||||
|
|
||||||
<p><a href="#toc">Back to top of page</a></p>
|
<p><a href="#toc">Back to top of page</a></p>
|
||||||
|
|
||||||
<h3 id="deepspeed-simplified"><strong>DeepSpeed Simplified:</strong></h3>
|
<h3 id="deepspeed-simplified"><strong>DeepSpeed Simplified:</strong></h3>
|
||||||
@@ -869,6 +956,10 @@ simple_webpage = """
|
|||||||
<li><strong>Smart Resource Use:</strong> Uses your computer's resources smartly, getting the most out of your hardware.</li>
|
<li><strong>Smart Resource Use:</strong> Uses your computer's resources smartly, getting the most out of your hardware.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<img src="/static/deepspeedexample.jpg" alt="DeepSpeed on vs off">
|
||||||
|
</div>
|
||||||
|
|
||||||
<p><strong>Note:</strong> DeepSpeed only works with the XTTSv2 Local model.</p>
|
<p><strong>Note:</strong> DeepSpeed only works with the XTTSv2 Local model.</p>
|
||||||
<p><strong>Note:</strong> Requires Nvidia Cuda Toolkit installation and correct CUDA_HOME path configuration.</p>
|
<p><strong>Note:</strong> Requires Nvidia Cuda Toolkit installation and correct CUDA_HOME path configuration.</p>
|
||||||
|
|
||||||
@@ -877,7 +968,7 @@ simple_webpage = """
|
|||||||
<p><a href="#toc">Back to top of page</a></p>
|
<p><a href="#toc">Back to top of page</a></p>
|
||||||
|
|
||||||
<h3 id="setup_deepspeed">Setup DeepSpeed</h3>
|
<h3 id="setup_deepspeed">Setup DeepSpeed</h3>
|
||||||
<p><strong>Note:</strong> DeepSpeed WILL throw up a load of errors if you have not installed it fully, correctly, or installed the Nvidia Cuda Toolkit and correctly set the CUDA_HOME environment variable or if load Text generation webUI via its start-up scripts.</p>
|
<p><strong>Note:</strong> DeepSpeed/AllTalk may warn if the Nvidia Cuda Toolkit and CUDA_HOME environment variables arent set. On Linux I believe you need these installed, on Windows, if you use the pre-built wheel it seems ok without.</p>
|
||||||
|
|
||||||
<h4>Linux - DeepSpeed - Installation Instructions</h4>
|
<h4>Linux - DeepSpeed - Installation Instructions</h4>
|
||||||
<ol>
|
<ol>
|
||||||
@@ -894,64 +985,34 @@ simple_webpage = """
|
|||||||
</ol>
|
</ol>
|
||||||
<p><a href="#toc">Back to top of page</a></p>
|
<p><a href="#toc">Back to top of page</a></p>
|
||||||
|
|
||||||
<h4>Windows - DeepSpeed Version 8.3 & CUDA 11.8 or CUDA 12.1 - Installation Instructions</h4>
|
<h4>Windows - DeepSpeed v11.1 or v11.2 Installation Instructions</h4>
|
||||||
<p>Currently DeepSpeed 8.3 is the latest build that works on Windows and it has to run inside a Python 3.9.18 environment. As such, either you need to have your own, already set up Python 3.9.18 environment and have installed the correct Text generation webUI requirements file into it. Or you can create a new Python environment. DeepSpeed version 9.x, 10.x, 11.x, and 12.x will all fail to compile <strong>(on Windows)</strong> for a multitude of reasons. As such, DeepSpeed v8.3 is the most recent build for Windows.</p>
|
<p>Currently/Officially only DeepSpeed v8.3 is installing on Windows, due to the broken installation routine by Microsoft, however, between myself and <a href="https://github.com/S95Sedan" target="_blank">S95Sedan</a> its now possible to install DeepSpeed v11.1 or v11.2 on Windows.</p>
|
||||||
|
|
||||||
<h4>DeepSpeed on Windows - <span class="option-a">Option A</span></h4>
|
<h4>DeepSpeed on Windows - <span class="option-a">Option A</span></h4>
|
||||||
<p><span class="option-a">Option A</span> is to fully go through the process of compiling DeepSpeed yourself. This takes a longer time to perform, but you can be sure it's set up for your system correctly.</p>
|
<p>This is to use the pre built DeepSpeed v11.1 wheel file. This is quite a quick process and should work for 99% of people.</p>
|
||||||
|
|
||||||
<h4>DeepSpeed on Windows - <span class="option-b">Option B</span></h4>
|
<p><strong>Note:</strong> In my tests, with this method you will <strong>not</strong> need to install the Nvidia CUDA toolkit to make this work, but AllTalk may warn you when starting DeepSpeed that it doesn't see the CUDA Toolkit; however, it works fine for TTS purposes.</p>
|
||||||
<p><span class="option-b">Option B</span> is to download someone else's precompiled wheels. If you can find someone's precompiled wheel file, you only need to follow <span class="option-b">Option B</span>.</p>
|
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li>(<span class="option-a">OPTION A</span>) Download the 8.3 release of <a href="https://github.com/microsoft/DeepSpeed/releases/tag/v0.8.3">DeepSpeed</a> and extract it to a folder.</li>
|
<li>Download the file <a href="https://drive.google.com/file/d/1PFsf6uSPY5Cb4o9VxiZ7DLv-j35L7Y41/view?usp=sharing" target="_blank">deepspeed-0.11.1+e9503fe-cp311-cp311-win_amd64.whl</a> by clicking the <strong>download</strong> icon at the top right of the screen and save the file it inside your <strong>text-generation-webui</strong> folder.</li>
|
||||||
<li>(<span class="option-a">OPTION A</span>) Install Visual C++ build tools, such as <a href="https://learn.microsoft.com/en-us/visualstudio/releases/2019/redistribution#vs2019-download">VS2019 C++ x64/x86</a> build tools.</li>
|
|
||||||
<li>(<span class="option-a">OPTION A</span> <span class="option-b">and B</span>) Download and install the <a href="https://developer.nvidia.com/cuda-toolkit-archive">Nvidia Cuda Toolkit 11.8 OR 12.1</a> <b>(11.8 or 12.1)</b></li>
|
|
||||||
<li>(<span class="option-a">OPTION A</span> <span class="option-b">and B</span>) Edit your Windows environment variables to ensure that CUDA_HOME and CUDA_PATH are set to your Nvidia Cuda Toolkit path. (The folder <strong>above</strong> the bin folder that <strong>nvcc.exe</strong> is installed in). Examples are:<br>
|
|
||||||
<br>CUDA 11.8<br><br>
|
|
||||||
<code>CUDA_HOME=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8</code><br>
|
|
||||||
<code>CUDA_PATH=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8</code><br>
|
|
||||||
<br>
|
|
||||||
CUDA 12.1<br><br>
|
|
||||||
<code>CUDA_HOME=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1</code><br>
|
|
||||||
<code>CUDA_PATH=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1</code><br><br>
|
|
||||||
|
|
||||||
It is possible to permanently set these or use the <code>set</code> command at the command prompt when inside your python environment e.g. <b>set CUDA_HOME=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1'</b>. You can then just type <code>set</code> again, and it will show you the list of all currently set environment variables so that you can confirm you have them set correctly.
|
<li>At a command prompt window, move into your <strong>text-generation-webui folder</strong>, you can now start the Python environment for text-generation-webui:
|
||||||
</li>
|
<br><code>cmd_windows.bat</code></li>
|
||||||
<li>(<span class="option-a">OPTION A</span> <span class="option-b">and B</span>) <strong>Currently Python versions 3.9.x are supported</strong>. If you do not have a Python environment already created, you can install <a href="https://docs.conda.io/projects/miniconda/en/latest/miniconda-install.html">Miniconda</a>, then at a command prompt, create and activate your environment with:
|
|
||||||
<br><br><code>conda create -n pythonenv python=3.9.18</code>
|
<li>With the file that you saved in the <strong>text-generation-webui folder</strong>, you now type the following:
|
||||||
<br><br><code>activate pythonenv</code>
|
<br><code>pip install "deepspeed-0.11.1+e9503fe-cp311-cp311-win_amd64.whl"</code></li>
|
||||||
</li>
|
|
||||||
<li>(<span class="option-a">OPTION A</span> <span class="option-b">and B</span>) Launch the Command Prompt <strong>cmd</strong> with <strong>Administrator privilege</strong> as it requires admin to allow creating symlink folders.</li>
|
<li>This should install through cleanly and you should now have DeepSpeed v11.1 installed within the Python 3.11 environment of text-generation-webui.</li>
|
||||||
<li>(<span class="option-a">OPTION A</span> <span class="option-b">and B</span>) Install <a href="https://pytorch.org/get-started/previous-versions/#v210">PyTorch</a>, 2.1.0 with CUDA 11.8 or CUDA 12.1 into your Python 3.9.x environment e.g.<br><br>
|
|
||||||
CUDA 11.8<br>
|
<li>When you start up text-generation-webui, and AllTalk starts, you should see <strong>[AllTalk Startup] DeepSpeed Detected</strong></li>
|
||||||
<br><code>activate pythonenv</code> (activate your python environment)<br>
|
|
||||||
<br><code>conda install pytorch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 pytorch-cuda=11.8 -c pytorch -c nvidia</code><br>
|
<li>Within AllTalk, you will now have a checkbox for <strong>Activate DeepSpeed</strong> though remember you can only change <strong>1x setting every 15 or so seconds</strong>, so don't try to activate DeepSpeed <strong>and</strong> LowVRAM/Change your model simultaneously. Do one of those, wait 15-20 seconds until the change is confirmed in the terminal/command prompt, then you can change the other. When you are happy it works, you can set the default start-up settings in the settings page.</li>
|
||||||
<br>CUDA 12.1<br>
|
|
||||||
<br><code>activate pythonenv</code> (activate your python environment)<br>
|
|
||||||
<br><code>conda install pytorch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 pytorch-cuda=12.1 -c pytorch -c nvidia</code>
|
|
||||||
</li>
|
|
||||||
<li>(<span class="option-a">OPTION A</span> <span class="option-b">and B</span>) In your python environment double-check that your <b>CUDA_HOME</b> and <b>CUDA_PATH</b> are still pointing to the correct location.
|
|
||||||
<br>Type <code>set</code> to list and check the Windows environment variables. Refer to step 4 if not.
|
|
||||||
</li>
|
|
||||||
<li>(<span class="option-a">OPTION A</span> <span class="option-b">and B</span>) Navigate to your deepspeed folder in the Command Prompt:<code>cd c:\deepspeed</code> (wherever you extracted it to)
|
|
||||||
</li>
|
|
||||||
<li>(<span class="option-a">OPTIONAL A</span>) You can try using the <strong>build_win.bat</strong> however you may need to set options to not install certain features e.g. <strong>set DS_BUILD_AIO=0</strong> <a href="https://www.deepspeed.ai/tutorials/advanced-install/#pre-install-deepspeed-ops">https://www.deepspeed.ai/tutorials/advanced-install/#pre-install-deepspeed-ops</a>. Type the following into the command prompt:
|
|
||||||
<br><br><code>set DS_BUILD_AIO=0</code>
|
|
||||||
<br><br><code>set DS_BUILD_SPARSE_ATTN=0</code>
|
|
||||||
<br><br><code>set DS_BUILD_EVOFORMER_ATTN=0</code>
|
|
||||||
<br><br><code>build_win.bat</code> (This will start building your wheel file and may take a while)
|
|
||||||
</li>
|
|
||||||
<li>(<span class="option-a">OPTION A</span> <span class="option-b">and B</span>) Now <strong>cd dist</strong> to go into your <strong>dist</strong> folder or wherever you have put your downloaded wheel file and you can now <strong>pip install deepspeed-_YOURFILENAME_.whl</strong> (or whatever your WHL file is called).
|
|
||||||
<br><strong><br>Note:</strong> You can run <code>ds_report</code> when you have installed DeepSpeed on your system to see if it is working correctly
|
|
||||||
</li>
|
|
||||||
<li>(<span class="option-a">OPTION A</span> <span class="option-b">and B</span>) Move into your Text generation webUI folder e.g. <code>cd Text generation webUI</code></li>
|
|
||||||
<li>(<span class="option-a">OPTION A</span> <span class="option-b">and B</span>) Don't forget to have <code>pip install -r requirements.txt</code> or whichever requirements file you want to use for your system, within the Text generation webUI folder.</li>
|
|
||||||
<li>(<span class="option-a">OPTION A</span> <span class="option-b">and B</span>) Start the text-generation=web-ui with Python e.g. <code>python server.py</code> ensuring to activate your extensions.
|
|
||||||
<br><strong><br>Note:</strong> you can't use <strong>start_windows.bat</strong> or <strong>cmd_windows.bat</strong> because it will use a different environment, incorrect version of Python and it will overwrite the CUDA_HOME path.
|
|
||||||
</li>
|
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
<h4>DeepSpeed on Windows - <span class="option-b">Option B</span></h4>
|
||||||
|
<p>Due to the complexity of this, Im not keeping the instructions within this document as it would be too complex to format.</p>
|
||||||
|
<p>As such, the instuctions can be found on this <a href="https://github.com/erew123/alltalk_tts?tab=readme-ov-file#-option-2---a-bit-more-complicated" target="_blank">link</a>
|
||||||
|
|
||||||
<p><a href="#toc">Back to top of page</a></p>
|
<p><a href="#toc">Back to top of page</a></p>
|
||||||
|
|
||||||
<h2 id="other-features"><strong>Other Features of AllTalk TTS Extension for Text generation webUI</strong></h2>
|
<h2 id="other-features"><strong>Other Features of AllTalk TTS Extension for Text generation webUI</strong></h2>
|
||||||
@@ -971,6 +1032,75 @@ simple_webpage = """
|
|||||||
</ul>
|
</ul>
|
||||||
<p><a href="#toc">Back to top of page</a></p>
|
<p><a href="#toc">Back to top of page</a></p>
|
||||||
|
|
||||||
|
<h3 id="demotesttts">Demo/Test TTS</h3>
|
||||||
|
|
||||||
|
<div id="container">
|
||||||
|
<form method="post" action="/tts-demo-request" id="ttsForm">
|
||||||
|
<label for="text">Text:</label>
|
||||||
|
<textarea id="text" name="text" rows="4" required></textarea>
|
||||||
|
|
||||||
|
<label for="voice">Voice:</label>
|
||||||
|
<input type="text" id="voice" name="voice" value="female_01.wav" required>
|
||||||
|
|
||||||
|
<label for="language">Language:</label>
|
||||||
|
<select id="language" name="language" value="English" required>
|
||||||
|
<option value="en" selected>English</option>
|
||||||
|
<option value="ar">Arabic</option>
|
||||||
|
<option value="zh-cn">Chinese</option>
|
||||||
|
<option value="cs">Czech</option>
|
||||||
|
<option value="nl">Dutch</option>
|
||||||
|
<option value="fr">French</option>
|
||||||
|
<option value="de">German</option>
|
||||||
|
<option value="hu">Hungarian</option>
|
||||||
|
<option value="it">Italian</option>
|
||||||
|
<option value="ja">Japanese</option>
|
||||||
|
<option value="ko">Korean</option>
|
||||||
|
<option value="pl">Polish</option>
|
||||||
|
<option value="pt">Portuguese</option>
|
||||||
|
<option value="ru">Russian</option>
|
||||||
|
<option value="es">Spanish</option>
|
||||||
|
<option value="tr">Turkish</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<label for="outputFile">Output File:</label>
|
||||||
|
<input type="text" id="outputFile" name="output_file" value="demo_output.wav" required>
|
||||||
|
|
||||||
|
<!-- Audio player with autoplay -->
|
||||||
|
<audio controls autoplay id="audioSource">
|
||||||
|
<source type="audio/wav" />
|
||||||
|
Your browser does not support the audio element.
|
||||||
|
</audio>
|
||||||
|
<span id="outputFilePath" style="height: 0px;">{{ output_file_path }}</span>
|
||||||
|
<button type="submit">Generate TTS</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const form = document.getElementById('ttsForm');
|
||||||
|
form.addEventListener('submit', async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const formData = new FormData(form);
|
||||||
|
const response = await fetch('/tts-demo-request', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
// Update the generated audio file path
|
||||||
|
const outputFilePath = document.getElementById('outputFilePath');
|
||||||
|
outputFilePath.textContent = result.output_file_path;
|
||||||
|
|
||||||
|
// Update the audio player source
|
||||||
|
const audioPlayer = document.getElementById('audioSource');
|
||||||
|
audioPlayer.src = `/audio/${result.output_file_path}`;
|
||||||
|
audioPlayer.load(); // Reload the audio player
|
||||||
|
audioPlayer.play(); // Play the audio;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<p><a href="#toc">Back to top of page</a></p>
|
||||||
|
|
||||||
<h3 id="customTTSmodels">Custom TTS Models and Model path</h3>
|
<h3 id="customTTSmodels">Custom TTS Models and Model path</h3>
|
||||||
|
|
||||||
<p>Its possible to set a custom model for the <strong>API Local</strong> and<strong> XTTSv2</strong> Local methods, or ideed point it at the same model that <strong>API TTS</strong> uses (wherever it is stored on your OS of choice). Many people did not like the sound quality of the Coqui <strong>2.0.<span style="color:#e74c3c">3</span></strong> model, and as such the AllTalk tts extension downloads the <strong>2.0.<span style="color:#2980b9">2</span></strong> model seperately to the <strong>2.0.<span style="color:#e74c3c">3</span></strong> model that TTS service downloads and manages. Typically the <strong>2.0.<span style="color:#2980b9">2</span></strong> model is stored in your <strong>/extensions/alltalk_tts/models</strong> folder and it is always downloaded on first start-up of the AllTalk_tts extension. However, you may either want to use a custom model version of your choosing, or point it to a different path on your system, or even point it so that API Local and XTTSv2 <strong>both</strong> use the same model that API TTS is using.</p>
|
<p>Its possible to set a custom model for the <strong>API Local</strong> and<strong> XTTSv2</strong> Local methods, or ideed point it at the same model that <strong>API TTS</strong> uses (wherever it is stored on your OS of choice). Many people did not like the sound quality of the Coqui <strong>2.0.<span style="color:#e74c3c">3</span></strong> model, and as such the AllTalk tts extension downloads the <strong>2.0.<span style="color:#2980b9">2</span></strong> model seperately to the <strong>2.0.<span style="color:#e74c3c">3</span></strong> model that TTS service downloads and manages. Typically the <strong>2.0.<span style="color:#2980b9">2</span></strong> model is stored in your <strong>/extensions/alltalk_tts/models</strong> folder and it is always downloaded on first start-up of the AllTalk_tts extension. However, you may either want to use a custom model version of your choosing, or point it to a different path on your system, or even point it so that API Local and XTTSv2 <strong>both</strong> use the same model that API TTS is using.</p>
|
||||||
@@ -1099,10 +1229,12 @@ simple_webpage = """
|
|||||||
<h3>Thanks to</h3>
|
<h3>Thanks to</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://github.com/daswer123" target="_blank">daswer123 GitHub Profile</a> (Assistance with cuda to cpu moving)</li>
|
<li><a href="https://github.com/daswer123" target="_blank">daswer123 GitHub Profile</a> (Assistance with cuda to cpu moving)</li>
|
||||||
|
<li><a href="https://github.com/S95Sedan" target="_blank">S95Sedan GitHub Profile</a> (Editing the Microsoft DeepSpeed v11.x installation files so they work)</li>
|
||||||
<li><a href="https://github.com/kanttouchthis" target="_blank">kanttouchthis GitHub Profile</a> (Portions of orginal Coquii_TTS extension)</li>
|
<li><a href="https://github.com/kanttouchthis" target="_blank">kanttouchthis GitHub Profile</a> (Portions of orginal Coquii_TTS extension)</li>
|
||||||
<li><a href="https://github.com/kanttouchthis" target="_blank">Wuzzooy GitHub Profile</a> (Trying out the code while in development)</li>
|
<li><a href="https://github.com/kanttouchthis" target="_blank">Wuzzooy GitHub Profile</a> (Trying out the code while in development)</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p><a href="#toc">Back to top of page</a></p>
|
<p><a href="#toc">Back to top of page</a></p>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -1121,7 +1253,6 @@ async def ready():
|
|||||||
async def read_root():
|
async def read_root():
|
||||||
return HTMLResponse(content=simple_webpage, status_code=200)
|
return HTMLResponse(content=simple_webpage, status_code=200)
|
||||||
|
|
||||||
|
|
||||||
# Start Uvicorn Webserver
|
# Start Uvicorn Webserver
|
||||||
host_parameter = {params["ip_address"]}
|
host_parameter = {params["ip_address"]}
|
||||||
port_parameter = str(params["port_number"])
|
port_parameter = str(params["port_number"])
|
||||||
|
|||||||
Reference in new issue
Block a user