diff --git a/diagnostics.py b/diagnostics.py deleted file mode 100644 index 8bb45d1..0000000 --- a/diagnostics.py +++ /dev/null @@ -1,325 +0,0 @@ -try: - import platform - import subprocess - import logging - from importlib_metadata import distributions - import torch - import os # Import the os module - import re - import sys - import glob - import site - import textwrap - import torch - import packaging.version - import packaging.specifiers - from packaging.specifiers import SpecifierSet - from packaging.specifiers import SpecifierSet - from packaging.version import parse as parse_version - from pathlib import Path -except ImportError as e: - print(f"\033[91mError importing module: {e}\033[0m\n") - print("\033[94mPlease ensure you started the Text-generation-webUI Python environment with either\033[0m") - print("\033[92mcmd_linux.sh\033[0m, \033[92mcmd_windows.bat\033[0m, \033[92mcmd_macos.sh\033[0m, or \033[92mcmd_wsl.bat\033[0m") - print("\033[94mfrom the text-generation-webui directory, and then try running the diagnostics again.\033[0m") - exit(1) - -this_dir = Path(__file__).parent - -try: - import psutil -except ImportError: - print("psutil not found. Installing...") - subprocess.run(['pip', 'install', 'psutil']) - import psutil - -def get_requirements_file(): - this_dir = Path(__file__).parent # Assuming 'this_dir' is defined as the script's directory - requirements_dir = this_dir / 'system' / 'requirements' - requirements_files = list(requirements_dir.glob('requirements*.txt')) # Using pathlib for globbing - - if not requirements_files: - print("\033[91mNo requirements files found.\033[0m") - return None - - print("\033[94m\nSelect a requirements file to check against (or press Enter for default 'requirements.txt'):\033[0m\n") - for i, file_path in enumerate(requirements_files, start=1): - print(f" {i}. {file_path.name}") # Only print the filename - - choice = input("\nEnter the number of your choice: ") - try: - choice = int(choice) - 1 - return str(requirements_files[choice]) # Return the full path as a string - except (ValueError, IndexError): - return str(requirements_dir / "requirements.txt") # Return the default path as a string - -# Set up logging with filemode='w' -logging.basicConfig(filename='diagnostics.log', - filemode='w', - level=logging.INFO, - format='%(message)s') # Custom format - -# Function to get GPU information using subprocess -def get_gpu_info(): - try: - result = subprocess.run(['nvidia-smi'], stdout=subprocess.PIPE, text=True) - return result.stdout - except FileNotFoundError: - return "NVIDIA GPU information not available" - -def get_cpu_info(): - cpu_info = { - 'physical_cores': psutil.cpu_count(logical=False), - 'total_cores': psutil.cpu_count(logical=True), - 'max_frequency': psutil.cpu_freq().max - } - return cpu_info - -def get_disk_info(): - disk_info = [] - partitions = psutil.disk_partitions() - for p in partitions: - usage = psutil.disk_usage(p.mountpoint) - disk_info.append(f" Drive: {p.device} | Total: {usage.total / (1024 ** 3):.2f} GB | Used: {usage.used / (1024 ** 3):.2f} GB | Free: {usage.free / (1024 ** 3):.2f} GB | Type: {p.fstype}") - return disk_info - -# Function to check if a port is in use -def is_port_in_use(port): - for conn in psutil.net_connections(): - if conn.laddr.port == port: - return True - return False - -def satisfies_wildcard(installed_version, required_version): - if '*' in required_version: - required_parts = required_version.split('.') - installed_parts = installed_version.split('.') - for req, inst in zip(required_parts, installed_parts): - if req != '*' and req != inst: - return False - return True - return False - -def test_cuda(): - cuda_available = torch.cuda.is_available() - if cuda_available: - try: - # Attempt to create a tensor on GPU - torch.tensor([1.0, 2.0]).cuda() - return "Success - CUDA is available and working." - except Exception as e: - return f"Fail - CUDA is available but not working. Error: {e}" - else: - return "Fail - CUDA is not available." - -def find_files_in_path_with_wildcard(pattern): - # Get the site-packages directory of the current Python environment - site_packages_path = site.getsitepackages() - found_paths = [] - # Adjust the sub-directory based on the operating system - sub_directory = "nvidia/cublas" - if platform.system() == "Linux": - sub_directory = os.path.join(sub_directory, "lib") - else: - sub_directory = os.path.join(sub_directory, "bin") - # Iterate over each site-packages directory (there can be more than one) - for directory in site_packages_path: - # Construct the search directory path - search_directory = os.path.join(directory, sub_directory) - # Use glob to find all files matching the pattern in this directory - for file_path in glob.glob(os.path.join(search_directory, pattern)): - if os.path.isfile(file_path): # Ensure it's a file - found_paths.append(file_path) - return found_paths - -# Function to log and print system information -def log_system_info(): - # System information - os_version = platform.system() + " " + platform.version() - - # Get CUDA_HOME environment variable - cuda_home = os.environ.get('CUDA_HOME', 'N/A') - - gpu_info = get_gpu_info() - - # Python environment information - python_version = platform.python_version() - - # Torch version - torch_version = torch.__version__ - cuda_test_result = test_cuda() - cpu_info = get_cpu_info() - disk_info = get_disk_info() - - # System RAM using psutil - try: - virtual_memory = psutil.virtual_memory() - total_ram = f"{virtual_memory.total / (1024 ** 3):.2f} GB" - available_ram = f"{virtual_memory.available / (1024 ** 3):.2f} GB" - system_ram = f"{available_ram} available out of {total_ram} total" - except NameError: - print("psutil is not installed. Unable to check system RAM.") - system_ram = "N/A" - - # Port check (if psutil is available) - port_status = "N/A" - if 'psutil' in globals(): - port_to_check = 7851 - if is_port_in_use(port_to_check): - port_status = f"Port {port_to_check} is in use." - else: - port_status = f"Port {port_to_check} is available." - - # Package versions using importlib_metadata - package_versions = {d.metadata['Name']: d.version for d in distributions()} - - # Python environment information - python_executable = sys.executable - python_version_info = sys.version_info - python_virtual_env = os.environ.get('VIRTUAL_ENV', 'N/A') - - # Conda environment information - conda_env = os.environ.get('CONDA_DEFAULT_ENV', 'N/A') - - # Get Path environment information - search_path = sys.path - path_env = os.environ.get('PATH', 'N/A') - - # Check for cublas - file_name = 'cublas64_11.*' if platform.system() == "Windows" else 'libcublas.so.11*' - found_paths = find_files_in_path_with_wildcard(file_name) - - # Compare with requirements file - requirements_file = get_requirements_file() - if requirements_file: - required_packages = {} - installed_packages = {} - - try: - with open(requirements_file, 'r') as req_file: - requirements = [line.strip() for line in req_file] - for req in requirements: - # Use regular expression to parse package name and version - match = re.match(r'([^\s>=]+)\s*([>=<]+)\s*([^,]+)', req) - if match: - package_name, operator, version_spec = match.groups() - installed_version = package_versions.get(package_name, 'Not installed') - if installed_version != 'Not installed': - required_packages[package_name] = (operator, version_spec) - installed_packages[package_name] = installed_version - except FileNotFoundError: - print(f"\n{requirements_file} not found. Skipping version checks.") - logging.info(f"NOTE {requirements_file} not found. Skipping version checks.") - - # Log and print information - logging.info(f"OPERATING SYSTEM:") - logging.info(f" OS Version: {os_version}") - logging.info(f" Note: Windows 11 will list as build is 10.x.22xxx") - logging.info(f"\nHARDWARE ENVIRONMENT:") - logging.info(f" CPU: Physical Cores: {cpu_info['physical_cores']}, Total Cores: {cpu_info['total_cores']}, Max Frequency: {cpu_info['max_frequency']} MHz") - logging.info(f" System RAM: {system_ram}") - logging.info(f"\nGPU INFORMATION:{gpu_info}") - logging.info("DISK INFORMATION:") - for disk in disk_info: - logging.info(disk) - logging.info("\nNETWORK PORT:") - logging.info(f" Port Status: {port_status}") - logging.info("\nCUDA:") - logging.info(f" CUDA Working: {cuda_test_result}") - logging.info(f" CUDA_HOME: {cuda_home}") - if found_paths: - logging.info(f" Cublas64_11 Path: {', '.join(found_paths)}") - else: - logging.info(f" Cublas64_11 Path: Not found in any search path directories.") - logging.info("\nPYTHON & PYTORCH:") - logging.info(f" Torch Version: {torch_version}") - logging.info(f" Python Version: {platform.python_version()}") - logging.info(f" Python Version Info: {python_version_info}") - logging.info(f" Python Executable: {python_executable}") - logging.info(f" Python Virtual Environment: {python_virtual_env} (Should be N/A when in Text-generation-webui Conda Python environment)") - logging.info(f" Conda Environment: {conda_env}") - logging.info("\nPython Search Path:") - for path in search_path: - logging.info(f" {path}") - logging.info("\nOS SEARCHPATH ENVIRONMENT:") - for path in path_env.split(';'): - logging.info(f" {path}") - if required_packages: # Check if the dictionary is not empty - logging.info("\nPACKAGE VERSIONS vs REQUIREMENTS FILE:") - max_package_length = max(len(package) for package in required_packages.keys()) - for package_name, (operator, required_version) in required_packages.items(): - installed_version = installed_packages.get(package_name, 'Not installed') - logging.info(f" {package_name.ljust(max_package_length)} Required: {operator} {required_version.ljust(12)} Installed: {installed_version}") - logging.info("\nPYTHON PACKAGES:") - for package, version in package_versions.items(): - logging.info(f" {package}>= {version}") - - # Print to screen - print(f"\n\033[94mOS Version:\033[0m \033[92m{os_version}\033[0m") - print(f"\033[94mOS Ver note:\033[0m \033[92m(Windows 11 will say build is 10.x.22xxx)\033[0m") - print(f"\033[94mSystem RAM:\033[0m \033[92m{system_ram}\033[0m") - for disk in disk_info: - print(f"\033[94mDisk:\033[0m \033[92m{disk}\033[0m") - print(f"\033[94m\nGPU Information:\033[0m {gpu_info}") - print(f"\033[94mPort Status:\033[0m \033[92m{port_status}\033[0m\n") - if "Fail" in cuda_test_result: - print(f"\033[91mCUDA Working:\033[0m \033[91m{cuda_test_result}\033[0m") - else: - print(f"\033[94mCUDA Working:\033[0m \033[92m{cuda_test_result}\033[0m") - print(f"\033[94mCUDA_HOME:\033[0m \033[92m{cuda_home}\033[0m") - if found_paths: - print(f"\033[94mCublas64_11 Path:\033[0m \033[92m{', '.join(found_paths)}\033[0m") - else: - print(f"\033[94mCublas64_11 Path:\033[0m \033[91mNot found in any search path directories.\033[0m") - print(f"\033[94m\nTorch Version:\033[0m \033[92m{torch_version}\033[0m") - print(f"\033[94mPython Version:\033[0m \033[92m{platform.python_version()}\033[0m") - print(f"\033[94mPython Executable:\033[0m \033[92m{python_executable}\033[0m") - print(f"\033[94mConda Environment:\033[0m \033[92m{conda_env}\033[0m") - print(f"\n\033[94mPython Search Path:\033[0m") - for path in search_path: - print(f" {path}") - if required_packages: # Check if the dictionary is not empty - print("\033[94m\nRequirements file package comparison:\033[0m") - max_package_length = max(len(package) for package in required_packages.keys()) - - for package_name, (operator, required_version) in required_packages.items(): - installed_version = installed_packages.get(package_name, 'Not installed') - - # Exclude build information (e.g., +cu118) before creating the SpecifierSet - required_version_no_build = required_version.split("+")[0] - - if '*' in required_version: - condition_met = satisfies_wildcard(installed_version, required_version) - else: - # Compare versions using packaging.version - required_specifier = SpecifierSet(f"{operator}{required_version_no_build}") - installed_version = parse_version(installed_version) - condition_met = installed_version in required_specifier - - color_required = "\033[92m" if condition_met else "\033[91m" - color_installed = "\033[92m" if condition_met else "\033[91m" - - # Print colored output - print(f" {package_name.ljust(max_package_length)} Required: {color_required}{operator} {required_version.ljust(12)}\033[0m Installed: {color_installed}{installed_version}\033[0m") - - print("\nOn Nvidia Graphics cards machines, if your \033[92mInstalled\033[0m version of \033[92mTorch\033[0m and \033[92mTorchaudio\033[0m does") - print("not have \033[92m+cu118\033[0m (Cuda 11.8) or \033[92m+cu121\033[0m (Cuda 12.1) listed after them, you do not have CUDA") - print("installed for Torch or Torchaudio in this Python environment. This will cause you problems") - print("with \033[94mAllTalk\033[0m and \033[94mFinetuning.\033[0m You may have to 'pip install' a new version of torch and") - print("torchaudio, using '\033[94m--upgrade --force-reinstall\033[0m' with the correct version of PyTorch for\033[0m") - print("your Python environment.\033[0m") - print("\033[94m\nRequirements file specifier meanings:\033[0m") - explanation = textwrap.dedent(""" - == Exact version != Any version except < Less than - <= Less than or equal to > Greater than >= Greater than or equal to - ~ Compatible release ; Environment marker AND Logical AND - OR Logical OR - """) - print(explanation.strip()) - print("") - print(f"\033[94mDiagnostic log created:\033[0m \033[92mdiagnostics.log. \033[94mA brief summary of results is displayed above on\033[0m") - print(f"\033[94mscreen. Please see the log file for more detail.\033[0m") - print(f"\033[94m\nPlease upload the log file with any support ticket.\033[0m") - -if __name__ == "__main__": - log_system_info()