mirror of
https://github.com/Pakobbix/StartUI-oobabooga-webui
synced 2026-01-02 12:00:33 +00:00
Compare commits
18 Commits
1.2
...
87a4c9fd2b
| Author | SHA1 | Date | |
|---|---|---|---|
| 87a4c9fd2b | |||
| 8217fb468d | |||
| ecc3131530 | |||
| 2df42114e9 | |||
| 99d1d92e14 | |||
| 8f4c651caa | |||
| 81cd746a46 | |||
| df82faee5a | |||
| e3780dafd5 | |||
| a062bbc7fa | |||
| 91e4e1f280 | |||
| 26c0cf03ca | |||
| 36b9d3e9b4 | |||
| 8ca048e94d | |||
| 44227e2627 | |||
| 3a2affa702 | |||
| 5c77703b38 | |||
| 17e02d982b |
14
.github/workflows/package.yml
vendored
14
.github/workflows/package.yml
vendored
@@ -1,23 +1,21 @@
|
|||||||
name: Package Release
|
name: Package Release
|
||||||
on:
|
on:
|
||||||
push:
|
workflow_dispatch:
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
package:
|
package:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: self-hosted
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [windows-latest, ubuntu-latest]
|
os: [windows-latest, ubuntu-latest]
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v3
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
@@ -31,7 +29,7 @@ jobs:
|
|||||||
cp webuiGUI.py dist/ # Copy webuiGUI.py to the dist directory
|
cp webuiGUI.py dist/ # Copy webuiGUI.py to the dist directory
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.os }}-binary-v1.2
|
name: ${{ matrix.os }}-binary-v1.3.1
|
||||||
path: dist
|
path: dist
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -7,7 +7,7 @@ As someone who isn't a professional programmer, I enjoy experimenting and findin
|
|||||||
WebUI StartGUI is a Python graphical user interface (GUI) written with PyQT5, that allows users to configure settings and start the oobabooga web user interface (WebUI). It provides a convenient way to adjust various parameters and launch the WebUI with the desired settings.
|
WebUI StartGUI is a Python graphical user interface (GUI) written with PyQT5, that allows users to configure settings and start the oobabooga web user interface (WebUI). It provides a convenient way to adjust various parameters and launch the WebUI with the desired settings.
|
||||||
|
|
||||||
## Current Features
|
## Current Features
|
||||||
- Select a model from a dropdown menu (with reload button if added while the StartUI is open)
|
- Select a model from a dropdown menu or none (with reload button if added while the StartUI is open)
|
||||||
- Choose wbits and groupsize options
|
- Choose wbits and groupsize options
|
||||||
- Select the operating mode (chat, cai-chat, notebook)
|
- Select the operating mode (chat, cai-chat, notebook)
|
||||||
- Choose between CPU, GPU or Autodevice
|
- Choose between CPU, GPU or Autodevice
|
||||||
@@ -21,10 +21,11 @@ WebUI StartGUI is a Python graphical user interface (GUI) written with PyQT5, th
|
|||||||
- Save settings to a profile
|
- Save settings to a profile
|
||||||
- Load profiles via Dropdown menu.
|
- Load profiles via Dropdown menu.
|
||||||
- Run the text-generation-webui Updater
|
- Run the text-generation-webui Updater
|
||||||
|
- StartUI Update Notification
|
||||||
|
|
||||||
## How to Use
|
## How to Use
|
||||||
1. Clone the repository or download the source code.
|
1. Clone the repository or download the source code.
|
||||||
2. Install the required dependencies listed in the `requirements.txt` file. (PyQT5 & gpustat)
|
2. Install the required dependencies listed in the `requirements.txt` file.
|
||||||
3. Run the `StartUI.py` script using Python `python3 StartUI.py`.
|
3. Run the `StartUI.py` script using Python `python3 StartUI.py`.
|
||||||
4. Configure the desired settings using the GUI elements.
|
4. Configure the desired settings using the GUI elements.
|
||||||
5. Click the "Save Settings" button to save the current settings to a profile.
|
5. Click the "Save Settings" button to save the current settings to a profile.
|
||||||
@@ -40,10 +41,15 @@ On Linux, you'll need to give StartUI the executable flag (`chmod +x StartUI` or
|
|||||||
The WebuiGUI.py must also be there, to handle the flags properly
|
The WebuiGUI.py must also be there, to handle the flags properly
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
V1.1 :\
|
V1.3 :\
|
||||||

|
<details>
|
||||||

|
|
||||||

|
<summary>Screenshots</summary>
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
291
StartUI.py
291
StartUI.py
@@ -1,12 +1,22 @@
|
|||||||
import sys, gpustat, os, json, subprocess, platform, psutil, urllib.request, re
|
import sys, gpustat, os, json, subprocess, platform, psutil, re, requests, darkdetect, qdarkstyle
|
||||||
from PyQt5.QtWidgets import QApplication, QMessageBox, QProgressBar, QMainWindow, QLabel, QVBoxLayout, QComboBox, QSlider, QCheckBox, QLineEdit, QFileDialog, QPushButton, QWidget, QListWidget, QListWidgetItem, QToolTip, QGridLayout, QRadioButton, QFrame, QDialog
|
from PyQt5.QtWidgets import QApplication, QToolBar, QMessageBox, QAction, QMainWindow, QLabel, QVBoxLayout, QComboBox, QSlider, QCheckBox, QLineEdit, QFileDialog, QPushButton, QWidget, QListWidget, QListWidgetItem, QGridLayout, QRadioButton, QFrame
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
|
|
||||||
|
version = "1.3.1"
|
||||||
|
|
||||||
profiles_folder = "./profiles"
|
profiles_folder = "./profiles"
|
||||||
os.makedirs(profiles_folder, exist_ok=True)
|
os.makedirs(profiles_folder, exist_ok=True)
|
||||||
model_folder = "./text-generation-webui/models"
|
model_folder = "./text-generation-webui/models"
|
||||||
extensions_folder = "./text-generation-webui/extensions"
|
extensions_folder = "./text-generation-webui/extensions"
|
||||||
loras_folder = "./text-generation-webui/loras"
|
loras_folder = "./text-generation-webui/loras"
|
||||||
|
characters_folder = "./text-generation-webui/characters"
|
||||||
|
try:
|
||||||
|
output = subprocess.check_output(['nvidia-smi'])
|
||||||
|
nvidia_gpu = True
|
||||||
|
except:
|
||||||
|
nvidia_gpu = False
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# # Get the absolute path of the script file
|
# # Get the absolute path of the script file
|
||||||
script_path = os.path.abspath(__file__)
|
script_path = os.path.abspath(__file__)
|
||||||
@@ -67,47 +77,102 @@ class MainWindow(QMainWindow):
|
|||||||
self.init_ui()
|
self.init_ui()
|
||||||
self.load_settings()
|
self.load_settings()
|
||||||
self.set_ram_slider_max()
|
self.set_ram_slider_max()
|
||||||
|
self.update_check()
|
||||||
|
|
||||||
def init_ui(self):
|
def init_ui(self):
|
||||||
self.setWindowTitle('StartUI for oobabooga webui')
|
self.setWindowTitle(f'StartUI for oobabooga webui v{version}')
|
||||||
#layout = QVBoxLayout()
|
# Menu Bar
|
||||||
|
menu = self.menuBar()
|
||||||
|
|
||||||
|
# Main menu
|
||||||
|
main_menu = menu.addMenu("StartUI")
|
||||||
|
main_menu.addAction("Exit", self.close)
|
||||||
|
|
||||||
|
# help menu
|
||||||
|
help_menu = menu.addMenu("Help")
|
||||||
|
|
||||||
|
# Help menu actions
|
||||||
|
# Github action
|
||||||
|
github_action = QAction("Github", self)
|
||||||
|
github_action.setStatusTip("Opens the Github Page")
|
||||||
|
github_action.triggered.connect(self.on_Github_clicked)
|
||||||
|
help_menu.addAction(github_action)
|
||||||
|
|
||||||
|
# Oobabooga action
|
||||||
|
oobabooga_action = QAction("oobabooga", self)
|
||||||
|
oobabooga_action.setStatusTip("Opens the oobabooga Github Page")
|
||||||
|
oobabooga_action.triggered.connect(self.on_oobabooga_clicked)
|
||||||
|
help_menu.addAction(oobabooga_action)
|
||||||
|
|
||||||
|
# Version action
|
||||||
|
version_action = QAction(f"Version: {version}", self)
|
||||||
|
version_action.setStatusTip("Shows the Version of StartUI")
|
||||||
|
help_menu.addAction(version_action)
|
||||||
|
version_action.triggered.connect(self.show_version_window)
|
||||||
|
|
||||||
|
# About Action
|
||||||
|
about_action = QAction("About", self)
|
||||||
|
about_action.setToolTip("Opens the About Page")
|
||||||
|
about_action.triggered.connect(self.show_about_window)
|
||||||
|
help_menu.addAction(about_action)
|
||||||
|
|
||||||
|
# seperator
|
||||||
|
help_menu.addSeparator()
|
||||||
|
|
||||||
|
# Report Bug
|
||||||
|
report_bug_action = QAction("Report Bug", self)
|
||||||
|
report_bug_action.setToolTip("Opens the Github Issue Page with creating a new issue")
|
||||||
|
report_bug_action.triggered.connect(self.on_report_bug_clicked)
|
||||||
|
help_menu.addAction(report_bug_action)
|
||||||
|
|
||||||
layout = QGridLayout()
|
layout = QGridLayout()
|
||||||
|
layout.setColumnMinimumWidth(0, 350)
|
||||||
layout.setColumnMinimumWidth(3, 30)
|
layout.setColumnMinimumWidth(3, 30)
|
||||||
|
|
||||||
# Model Dropdown
|
# Model Dropdown
|
||||||
# Get the list of model folders
|
# Get the list of model folders
|
||||||
model_folders = [name for name in os.listdir(model_folder) if os.path.isdir(os.path.join(model_folder, name))]
|
model_folders = [name for name in os.listdir(model_folder) if os.path.isdir(os.path.join(model_folder, name))]
|
||||||
self.model_dropdown = QComboBox()
|
self.model_dropdown = QComboBox()
|
||||||
|
self.model_dropdown.addItem("none")
|
||||||
self.model_dropdown.addItems(model_folders)
|
self.model_dropdown.addItems(model_folders)
|
||||||
layout.addWidget(QLabel("Choose Model:"))
|
layout.addWidget(QLabel("Choose Model:"))
|
||||||
self.model_dropdown.setToolTip("Select your prefered Model")
|
self.model_dropdown.setToolTip("Select your prefered Model")
|
||||||
layout.addWidget(self.model_dropdown, 1, 0)
|
layout.addWidget(self.model_dropdown, 1, 0)
|
||||||
|
|
||||||
self.model_type = QComboBox()
|
self.model_type = QComboBox()
|
||||||
self.model_type.addItems(["llama", "opt", "gptj", "none"])
|
self.model_type.addItems(["none", "llama", "opt", "gptj"])
|
||||||
layout.addWidget(QLabel("Choose Model Type:"), 3, 0)
|
layout.addWidget(QLabel("Choose Model Type:"), 3, 0)
|
||||||
self.model_type.setToolTip("Select the Model Type")
|
self.model_type.setToolTip("Select the Model Type")
|
||||||
layout.addWidget(self.model_type, 4, 0)
|
layout.addWidget(self.model_type, 4, 0)
|
||||||
|
|
||||||
|
self.character_to_load = QComboBox()
|
||||||
|
character_jsons = [file for file in os.listdir(characters_folder) if file.endswith(".json")]
|
||||||
|
without_suffix = [file.replace(".json", "") for file in character_jsons]
|
||||||
|
self.character_to_load.addItem("none")
|
||||||
|
self.character_to_load.addItems(without_suffix)
|
||||||
|
layout.addWidget(QLabel("Choose Character:"), 3, 1)
|
||||||
|
self.character_to_load.setToolTip("Select the Character you want to load")
|
||||||
|
layout.addWidget(self.character_to_load, 4, 1)
|
||||||
|
|
||||||
self.reload_model_button = QPushButton("Reload")
|
self.reload_model_button = QPushButton("Reload")
|
||||||
self.reload_model_button.setToolTip("Reloads the Names in the Models Folder")
|
self.reload_model_button.setToolTip("Reloads the Names in the Models Folder")
|
||||||
self.reload_model_button.clicked.connect(self.reload_models)
|
self.reload_model_button.clicked.connect(self.reload_models)
|
||||||
layout.addWidget(QLabel("Reload the Model list:"),0, 1)
|
layout.addWidget(QLabel("Reload the Model list:"),0, 1)
|
||||||
layout.addWidget(self.reload_model_button, 1, 1)
|
layout.addWidget(self.reload_model_button, 1, 1, 1 , 2)
|
||||||
|
|
||||||
# WBIT Dropdown Menu
|
# WBIT Dropdown Menu
|
||||||
self.wbit_dropdown = QComboBox()
|
self.wbit_dropdown = QComboBox()
|
||||||
self.wbit_dropdown.addItems(["1", "2", "3", "4","8", "none"])
|
self.wbit_dropdown.addItems(["none", "1", "2", "3", "4","8"])
|
||||||
layout.addWidget(QLabel("Choose Wbits:"),5, 0)
|
layout.addWidget(QLabel("Choose Wbits:"),5, 0)
|
||||||
self.wbit_dropdown.setToolTip("Select the bits quantization for this model\nExample: vicuna 7b 4bit you should choose 4.\nYou can keep it at none, the webui will determine it automatically if the wbits are mentioned in the name of the model")
|
self.wbit_dropdown.setToolTip("Select the bits quantization for this model\nExample: vicuna 7b 4bit you should choose 4.\nYou can keep it at none, the webui will determine it automatically if the wbits are mentioned in the name of the model")
|
||||||
layout.addWidget(self.wbit_dropdown, 6, 0)
|
layout.addWidget(self.wbit_dropdown, 6, 0)
|
||||||
|
|
||||||
# Groupsize Dropdown Menu
|
# Groupsize Dropdown Menu
|
||||||
self.gsize_dropdown = QComboBox()
|
self.gsize_dropdown = QComboBox()
|
||||||
self.gsize_dropdown.addItems(["32", "64", "128", "1024", "none"])
|
self.gsize_dropdown.addItems(["none", "32", "64", "128", "1024"])
|
||||||
layout.addWidget(QLabel("Choose Groupsize:"), 5, 1)
|
layout.addWidget(QLabel("Choose Groupsize:"), 5, 1)
|
||||||
self.gsize_dropdown.setToolTip("Select the groupsize used by the Model.\nExample: vicuna 7b 4bit-128g you should choose 128.\nYou can keep it at none, the webui will determine it automatically if the groupsize is mentioned in the name of the model")
|
self.gsize_dropdown.setToolTip("Select the groupsize used by the Model.\nExample: vicuna 7b 4bit-128g you should choose 128.\nYou can keep it at none, the webui will determine it automatically if the groupsize is mentioned in the name of the model")
|
||||||
layout.addWidget(self.gsize_dropdown, 6, 1)
|
layout.addWidget(self.gsize_dropdown, 6, 1, 1, 2)
|
||||||
|
|
||||||
# Mode Dropdown
|
# Mode Dropdown
|
||||||
self.mode_dropdown = QComboBox()
|
self.mode_dropdown = QComboBox()
|
||||||
@@ -119,7 +184,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.update_button = QPushButton("Update oobabooga")
|
self.update_button = QPushButton("Update oobabooga")
|
||||||
self.update_button.setToolTip("Starts the Update Routine for the text-generation-webui")
|
self.update_button.setToolTip("Starts the Update Routine for the text-generation-webui")
|
||||||
self.update_button.clicked.connect(self.on_update_button_clicked)
|
self.update_button.clicked.connect(self.on_update_button_clicked)
|
||||||
layout.addWidget(self.update_button, 8, 1)
|
layout.addWidget(self.update_button, 8, 1, 1, 2)
|
||||||
layout.addWidget(QLabel("Update the text-generation-webui:"), 7, 1)
|
layout.addWidget(QLabel("Update the text-generation-webui:"), 7, 1)
|
||||||
|
|
||||||
# Add horizontal line to seperate the CPU/GPU Settings
|
# Add horizontal line to seperate the CPU/GPU Settings
|
||||||
@@ -130,8 +195,13 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
# GPU Checkbox and Sliders
|
# GPU Checkbox and Sliders
|
||||||
self.gpu_radio_button = QRadioButton("Use GPU")
|
self.gpu_radio_button = QRadioButton("Use GPU")
|
||||||
self.gpu_radio_button.setToolTip("Choose if you want to use your GPU")
|
if nvidia_gpu:
|
||||||
self.gpu_radio_button.setChecked(True)
|
self.gpu_radio_button.setChecked(True)
|
||||||
|
self.gpu_radio_button.setToolTip("Choose if you want to use your GPU")
|
||||||
|
else:
|
||||||
|
self.gpu_radio_button.setToolTip("AMD or Intel GPU's are currently not supported.")
|
||||||
|
self.gpu_radio_button.setChecked(False)
|
||||||
|
self.gpu_radio_button.setEnabled(False)
|
||||||
layout.addWidget(self.gpu_radio_button, 10, 0)
|
layout.addWidget(self.gpu_radio_button, 10, 0)
|
||||||
|
|
||||||
self.cpu_radio_button = QRadioButton("Use CPU")
|
self.cpu_radio_button = QRadioButton("Use CPU")
|
||||||
@@ -141,35 +211,40 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
self.auto_radio_button = QRadioButton("Autodevice")
|
self.auto_radio_button = QRadioButton("Autodevice")
|
||||||
self.auto_radio_button.setToolTip("Let the webui decide whats best for you!")
|
self.auto_radio_button.setToolTip("Let the webui decide whats best for you!")
|
||||||
self.auto_radio_button.setChecked(False)
|
if nvidia_gpu:
|
||||||
|
self.auto_radio_button.setChecked(False)
|
||||||
|
else:
|
||||||
|
self.auto_radio_button.setChecked(True)
|
||||||
layout.addWidget(self.auto_radio_button, 10, 2)
|
layout.addWidget(self.auto_radio_button, 10, 2)
|
||||||
|
|
||||||
self.gpu_radio_button.toggled.connect(self.on_gpu_radio_button_toggled)
|
self.gpu_radio_button.toggled.connect(self.on_gpu_radio_button_toggled)
|
||||||
self.cpu_radio_button.toggled.connect(self.on_cpu_radio_button_toggled)
|
self.cpu_radio_button.toggled.connect(self.on_cpu_radio_button_toggled)
|
||||||
self.auto_radio_button.toggled.connect(self.on_auto_radio_button_toggled)
|
self.auto_radio_button.toggled.connect(self.on_auto_radio_button_toggled)
|
||||||
|
|
||||||
self.gpu_vram_sliders = []
|
if nvidia_gpu:
|
||||||
self.gpu_vram_labels = []
|
self.gpu_vram_sliders = []
|
||||||
self.gpu_labels = []
|
self.gpu_vram_labels = []
|
||||||
|
self.gpu_labels = []
|
||||||
|
gpu_stats = gpustat.GPUStatCollection.new_query()
|
||||||
|
|
||||||
gpu_stats = gpustat.GPUStatCollection.new_query()
|
for i, gpu in enumerate(gpu_stats):
|
||||||
|
gpu_label = QLabel(f"{gpu.name} VRAM:")
|
||||||
|
gpu_label.setToolTip(f"Total VRAM: {gpu.memory_total} MiB\nUsed VRAM: {gpu.memory_used} MiB\nFree VRAM: {gpu.memory_free} MiB")
|
||||||
|
layout.addWidget(gpu_label, 11 + i, 0)
|
||||||
|
self.gpu_labels.append(gpu_label)
|
||||||
|
|
||||||
for i, gpu in enumerate(gpu_stats):
|
vram_slider = QSlider(Qt.Horizontal)
|
||||||
gpu_label = QLabel(f"{gpu.name} VRAM:")
|
vram_slider.setMaximum(int(gpu.memory_total / 1024))
|
||||||
gpu_label.setToolTip(f"Total VRAM: {gpu.memory_total} MiB\nUsed VRAM: {gpu.memory_used} MiB\nFree VRAM: {gpu.memory_free} MiB")
|
vram_slider.valueChanged.connect(lambda value, idx=i: self.on_vram_slider_changed(value, idx))
|
||||||
layout.addWidget(gpu_label, 11 + i, 0)
|
layout.addWidget(vram_slider, 11 + i, 1)
|
||||||
self.gpu_labels.append(gpu_label)
|
|
||||||
|
|
||||||
vram_slider = QSlider(Qt.Horizontal)
|
vram_value_label = QLabel("0 GiB")
|
||||||
vram_slider.setMaximum(int(gpu.memory_total / 1024))
|
layout.addWidget(vram_value_label, 11 + i, 2)
|
||||||
vram_slider.valueChanged.connect(lambda value, idx=i: self.on_vram_slider_changed(value, idx))
|
self.gpu_vram_labels.append(vram_value_label)
|
||||||
layout.addWidget(vram_slider, 11 + i, 1)
|
|
||||||
|
|
||||||
vram_value_label = QLabel("0 GiB")
|
self.gpu_vram_sliders.append(vram_slider)
|
||||||
layout.addWidget(vram_value_label, 11 + i, 2)
|
else:
|
||||||
self.gpu_vram_labels.append(vram_value_label)
|
gpu_stats = [""]
|
||||||
|
|
||||||
self.gpu_vram_sliders.append(vram_slider)
|
|
||||||
|
|
||||||
# Create the "Built-in RAM" label, slider, and value label
|
# Create the "Built-in RAM" label, slider, and value label
|
||||||
self.ram_label = QLabel("Built-in RAM:")
|
self.ram_label = QLabel("Built-in RAM:")
|
||||||
@@ -201,7 +276,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.pre_layer_slider.setSingleStep(1)
|
self.pre_layer_slider.setSingleStep(1)
|
||||||
layout.addWidget(QLabel("Pre-layer:"), 11 + len(gpu_stats), 0)
|
layout.addWidget(QLabel("Pre-layer:"), 11 + len(gpu_stats), 0)
|
||||||
self.pre_layer_slider.setToolTip("The number of layers to allocate to the GPU. Setting this parameter enables CPU offloading for 4-bit models.")
|
self.pre_layer_slider.setToolTip("The number of layers to allocate to the GPU. Setting this parameter enables CPU offloading for 4-bit models.")
|
||||||
layout.addWidget(self.pre_layer_slider)
|
layout.addWidget(self.pre_layer_slider, 11 + len(gpu_stats), 1)
|
||||||
self.pre_layer_slider.valueChanged.connect(self.on_pre_layer_slider_changed)
|
self.pre_layer_slider.valueChanged.connect(self.on_pre_layer_slider_changed)
|
||||||
|
|
||||||
self.pre_layer_value_label = QLabel("0")
|
self.pre_layer_value_label = QLabel("0")
|
||||||
@@ -414,6 +489,105 @@ class MainWindow(QMainWindow):
|
|||||||
self.load_button.clicked.connect(self.on_load_button_clicked)
|
self.load_button.clicked.connect(self.on_load_button_clicked)
|
||||||
layout.addWidget(self.load_button, 34 + len(gpu_stats), 1)
|
layout.addWidget(self.load_button, 34 + len(gpu_stats), 1)
|
||||||
|
|
||||||
|
# Show if Update is available
|
||||||
|
self.update_button_ui = QPushButton("Update\nAvailable")
|
||||||
|
self.update_button_ui.setToolTip("Shows if an update is available")
|
||||||
|
self.update_button_ui.setStyleSheet("QPushButton { color: #ff9999; font-weight: bold; }")
|
||||||
|
self.update_button_ui.clicked.connect(self.on_update_button_ui_clicked)
|
||||||
|
layout.addWidget(self.update_button_ui, 34 + len(gpu_stats), 2, 2, 2)
|
||||||
|
self.update_button_ui.setVisible(False)
|
||||||
|
|
||||||
|
def on_update_button_ui_clicked(self):
|
||||||
|
self.show_version_window()
|
||||||
|
|
||||||
|
def update_check(self):
|
||||||
|
latest_version = self.get_latest_version()
|
||||||
|
if latest_version and latest_version > version:
|
||||||
|
self.update_button_ui.setVisible(True)
|
||||||
|
|
||||||
|
def show_version_window(self):
|
||||||
|
latest_version = self.get_latest_version()
|
||||||
|
if latest_version and latest_version > version:
|
||||||
|
release_notes = self.get_release_notes()
|
||||||
|
update_text = f"A new version ({latest_version}) is available! Do you want to update?\n\n\n{release_notes}"
|
||||||
|
reply = QMessageBox.question(self, "Update Available", update_text, QMessageBox.Yes | QMessageBox.No)
|
||||||
|
if reply == QMessageBox.Yes:
|
||||||
|
release_url = f"https://github.com/Pakobbix/StartUI-oobabooga-webui/releases/tag/{latest_version}"
|
||||||
|
if sys.platform == "win32":
|
||||||
|
os.startfile(release_url)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
subprocess.Popen(["xdg-open", release_url])
|
||||||
|
except OSError:
|
||||||
|
self.show_error_message("Error", f"Could not open the link. Please open it manually.\n{release_url}")
|
||||||
|
|
||||||
|
def on_report_bug_clicked(self):
|
||||||
|
github_new_issue = "https://github.com/Pakobbix/StartUI-oobabooga-webui/issues/new"
|
||||||
|
if sys.platform == "win32":
|
||||||
|
os.startfile(github_new_issue)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
subprocess.Popen(["xdg-open", github_new_issue])
|
||||||
|
except OSError:
|
||||||
|
self.show_error_message("Error", f"Could not open the link. Please open it manually.\n{github_new_issue}")
|
||||||
|
|
||||||
|
def on_Github_clicked(self):
|
||||||
|
startui_url = "https://github.com/Pakobbix/StartUI-oobabooga-webui/"
|
||||||
|
if sys.platform == "win32":
|
||||||
|
os.startfile(startui_url)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
subprocess.Popen(["xdg-open", startui_url])
|
||||||
|
except OSError:
|
||||||
|
self.show_error_message("Error", f"Could not open the link. Please open it manually.\n{startui_url}")
|
||||||
|
|
||||||
|
def on_oobabooga_clicked(self):
|
||||||
|
oobabooga_url = "https://github.com/oobabooga/text-generation-webui"
|
||||||
|
if sys.platform == "win32":
|
||||||
|
os.startfile(oobabooga_url)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
subprocess.Popen(["xdg-open", oobabooga_url])
|
||||||
|
except OSError:
|
||||||
|
self.show_error_message("Error", f"Could not open the link. Please open it manually.\n{oobabooga_url}")
|
||||||
|
|
||||||
|
def get_latest_version(self):
|
||||||
|
try:
|
||||||
|
url = "https://api.github.com/repos/Pakobbix/StartUI-oobabooga-webui/releases/latest"
|
||||||
|
response = requests.get(url)
|
||||||
|
if response.status_code == 200:
|
||||||
|
latest_release = response.json()
|
||||||
|
tag_name = latest_release["tag_name"]
|
||||||
|
return tag_name
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error fetching latest version: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_release_notes(self):
|
||||||
|
try:
|
||||||
|
url = "https://api.github.com/repos/Pakobbix/StartUI-oobabooga-webui/releases/latest"
|
||||||
|
response = requests.get(url)
|
||||||
|
if response.status_code == 200:
|
||||||
|
latest_release = response.json()
|
||||||
|
release_notes = latest_release["body"]
|
||||||
|
return release_notes
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error fetching release notes: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def show_about_window(self, action):
|
||||||
|
latest_version = self.get_latest_version()
|
||||||
|
release_url = f"https://github.com/Pakobbix/StartUI-oobabooga-webui/releases/tag/{latest_version}"
|
||||||
|
if latest_version and latest_version > version:
|
||||||
|
about_text = f"A new version ({latest_version}) is available! Please <a href='{release_url}'>update.</a> <br><br>StartUI for oobabooga's webui.<br><br> Current Version: {version}<br><br>This is an GUI (Graphical User Interface), to set flags depending on the user selection."
|
||||||
|
else:
|
||||||
|
about_text = f"StartUI for oobabooga's webui.\n\nVersion: {version}\n\nThis is an GUI (Graphical User Interface), to set flags depending on the user selection."
|
||||||
|
QMessageBox.about(self, "About", about_text)
|
||||||
|
|
||||||
def on_use_extensions_checkbox_changed(self, state):
|
def on_use_extensions_checkbox_changed(self, state):
|
||||||
self.extensions_list.setVisible(state == Qt.Checked)
|
self.extensions_list.setVisible(state == Qt.Checked)
|
||||||
|
|
||||||
@@ -487,10 +661,11 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
def on_cpu_radio_button_toggled(self, checked):
|
def on_cpu_radio_button_toggled(self, checked):
|
||||||
# Hide/show GPU-related widgets
|
# Hide/show GPU-related widgets
|
||||||
for slider, label_vram, label_gpu in zip(self.gpu_vram_sliders, self.gpu_vram_labels, self.gpu_labels):
|
if nvidia_gpu:
|
||||||
slider.hide()
|
for slider, label_vram, label_gpu in zip(self.gpu_vram_sliders, self.gpu_vram_labels, self.gpu_labels):
|
||||||
label_vram.hide()
|
slider.hide()
|
||||||
label_gpu.hide()
|
label_vram.hide()
|
||||||
|
label_gpu.hide()
|
||||||
|
|
||||||
# Show RAM slider and value label
|
# Show RAM slider and value label
|
||||||
self.ram_label.setVisible(checked)
|
self.ram_label.setVisible(checked)
|
||||||
@@ -498,16 +673,19 @@ class MainWindow(QMainWindow):
|
|||||||
self.ram_value_label.setVisible(checked)
|
self.ram_value_label.setVisible(checked)
|
||||||
|
|
||||||
# Uncheck GPU and Autodevice radio buttons
|
# Uncheck GPU and Autodevice radio buttons
|
||||||
if checked:
|
if checked and nvidia_gpu:
|
||||||
self.gpu_radio_button.setChecked(False)
|
self.gpu_radio_button.setChecked(False)
|
||||||
self.auto_radio_button.setChecked(False)
|
self.auto_radio_button.setChecked(False)
|
||||||
|
elif checked and not nvidia_gpu:
|
||||||
|
self.auto_radio_button.setChecked(False)
|
||||||
|
|
||||||
def on_auto_radio_button_toggled(self, checked):
|
def on_auto_radio_button_toggled(self, checked):
|
||||||
# Hide/show GPU-related widgets
|
# Hide/show GPU-related widgets
|
||||||
for slider, label_vram, label_gpu in zip(self.gpu_vram_sliders, self.gpu_vram_labels, self.gpu_labels):
|
if nvidia_gpu:
|
||||||
slider.hide()
|
for slider, label_vram, label_gpu in zip(self.gpu_vram_sliders, self.gpu_vram_labels, self.gpu_labels):
|
||||||
label_vram.hide()
|
slider.hide()
|
||||||
label_gpu.hide()
|
label_vram.hide()
|
||||||
|
label_gpu.hide()
|
||||||
|
|
||||||
# Hide RAM slider and value label
|
# Hide RAM slider and value label
|
||||||
self.ram_label.hide()
|
self.ram_label.hide()
|
||||||
@@ -515,9 +693,11 @@ class MainWindow(QMainWindow):
|
|||||||
self.ram_value_label.hide()
|
self.ram_value_label.hide()
|
||||||
|
|
||||||
# Uncheck GPU and CPU radio buttons
|
# Uncheck GPU and CPU radio buttons
|
||||||
if checked:
|
if checked and nvidia_gpu:
|
||||||
self.gpu_radio_button.setChecked(False)
|
self.gpu_radio_button.setChecked(False)
|
||||||
self.cpu_radio_button.setChecked(False)
|
self.cpu_radio_button.setChecked(False)
|
||||||
|
elif checked and not nvidia_gpu:
|
||||||
|
self.cpu_radio_button.setChecked(False)
|
||||||
|
|
||||||
def on_listen_port_checkbox_changed(self, state):
|
def on_listen_port_checkbox_changed(self, state):
|
||||||
self.listen_port_textfield.setEnabled(state == Qt.Checked)
|
self.listen_port_textfield.setEnabled(state == Qt.Checked)
|
||||||
@@ -568,6 +748,7 @@ class MainWindow(QMainWindow):
|
|||||||
"authentication": self.authentication_checkbox.isChecked(), # Saves the state of the Authentication
|
"authentication": self.authentication_checkbox.isChecked(), # Saves the state of the Authentication
|
||||||
"authentication_file": self.choose_file_label.text(), # Save the authentication file path
|
"authentication_file": self.choose_file_label.text(), # Save the authentication file path
|
||||||
"gpu_vram": [slider.value() for slider in self.gpu_vram_sliders], # Saves the VRAM Values
|
"gpu_vram": [slider.value() for slider in self.gpu_vram_sliders], # Saves the VRAM Values
|
||||||
|
"character": self.character_to_load.currentText(), # Saves the Characters given in the Textbox
|
||||||
"use_extension": self.use_extensions_checkbox.isChecked(), # Saves the state of the Extension Checkbox
|
"use_extension": self.use_extensions_checkbox.isChecked(), # Saves the state of the Extension Checkbox
|
||||||
"extensions": [self.extensions_list.item(i).text() for i in range(self.extensions_list.count()) if self.extensions_list.item(i).checkState() == Qt.Checked], # Saves the chosen Extensions
|
"extensions": [self.extensions_list.item(i).text() for i in range(self.extensions_list.count()) if self.extensions_list.item(i).checkState() == Qt.Checked], # Saves the chosen Extensions
|
||||||
"use_lora": self.use_lora_checkbox.isChecked(), # Saves the state of the Lora Checkbox
|
"use_lora": self.use_lora_checkbox.isChecked(), # Saves the state of the Lora Checkbox
|
||||||
@@ -598,32 +779,36 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
# Add the chosen model to the command
|
# Add the chosen model to the command
|
||||||
chosen_model = self.model_dropdown.currentText()
|
chosen_model = self.model_dropdown.currentText()
|
||||||
command += f" --model {chosen_model}"
|
if self.model_dropdown.currentText() != "none":
|
||||||
|
command += f" --model {chosen_model}"
|
||||||
|
|
||||||
# Add the chosen model type to the command
|
# Add the chosen model type to the command
|
||||||
chosen_model_type = self.model_type.currentText()
|
chosen_model_type = self.model_type.currentText()
|
||||||
if self.model_type.currentText() != "none":
|
if self.model_type.currentText() != "none" and self.model_dropdown.currentText() != "none":
|
||||||
command += f" --model_type {chosen_model_type}"
|
command += f" --model_type {chosen_model_type}"
|
||||||
|
|
||||||
# Add loras to the command
|
# Add loras to the command
|
||||||
# if self.loras_checkbox.isChecked():
|
|
||||||
# loras = self.lora_list.item(i).text() for i in range(self.lora_list.count()) if self.lora_list.item(i).checkState() == Qt.Checked
|
|
||||||
# command += f" --lora {loras}"
|
|
||||||
loras = [self.lora_list.item(i).text() for i in range(self.lora_list.count()) if self.lora_list.item(i).checkState() == Qt.Checked]
|
loras = [self.lora_list.item(i).text() for i in range(self.lora_list.count()) if self.lora_list.item(i).checkState() == Qt.Checked]
|
||||||
if self.use_lora_checkbox.isChecked():
|
if self.use_lora_checkbox.isChecked() and self.model_dropdown.currentText() != "none":
|
||||||
if loras:
|
if loras:
|
||||||
command += f" --lora {' '.join(loras)}"
|
command += f" --lora {' '.join(loras)}"
|
||||||
|
|
||||||
|
# Add Characters to the command
|
||||||
|
chosen_characters = self.character_to_load.currentText()
|
||||||
|
if self.character_to_load.currentText() != "none":
|
||||||
|
command += f" --character {chosen_characters}"
|
||||||
|
print(chosen_characters)
|
||||||
|
|
||||||
# Adds wbits to the command, if not "none"
|
# Adds wbits to the command, if not "none"
|
||||||
chosen_wbits = self.wbit_dropdown.currentText()
|
chosen_wbits = self.wbit_dropdown.currentText()
|
||||||
if self.wbit_dropdown.currentText() != "none":
|
if self.wbit_dropdown.currentText() != "none":
|
||||||
if not self.cpu_radio_button.isChecked():
|
if not self.cpu_radio_button.isChecked() and self.model_dropdown.currentText() != "none":
|
||||||
command += f" --wbits {chosen_wbits}"
|
command += f" --wbits {chosen_wbits}"
|
||||||
|
|
||||||
# Adds Groupsize to the command, if not "none"
|
# Adds Groupsize to the command, if not "none"
|
||||||
chosen_gsize = self.gsize_dropdown.currentText()
|
chosen_gsize = self.gsize_dropdown.currentText()
|
||||||
if self.gsize_dropdown.currentText() != "none":
|
if self.gsize_dropdown.currentText() != "none":
|
||||||
if not self.cpu_radio_button.isChecked():
|
if not self.cpu_radio_button.isChecked() and self.model_dropdown.currentText() != "none":
|
||||||
command += f" --groupsize {chosen_gsize}"
|
command += f" --groupsize {chosen_gsize}"
|
||||||
|
|
||||||
# Add the chosen mode to the command (Chat, cai-chat, notebook)
|
# Add the chosen mode to the command (Chat, cai-chat, notebook)
|
||||||
@@ -742,7 +927,7 @@ class MainWindow(QMainWindow):
|
|||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
def on_update_button_clicked(self):
|
def on_update_button_clicked(self):
|
||||||
run_cmd_with_conda("python webuiGUI.py --update")
|
run_cmd_with_conda("python webuiGUI.py --update && exit")
|
||||||
|
|
||||||
def load_profile(self, profile_file):
|
def load_profile(self, profile_file):
|
||||||
with open(profile_file, "r") as file:
|
with open(profile_file, "r") as file:
|
||||||
@@ -797,6 +982,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.use_nocache_checkbox.setChecked(settings.get("nocache", False))
|
self.use_nocache_checkbox.setChecked(settings.get("nocache", False))
|
||||||
self.authentication_checkbox.setChecked(settings.get("authentication", False))
|
self.authentication_checkbox.setChecked(settings.get("authentication", False))
|
||||||
self.choose_file_label.setText(settings.get("authentication_file", ""))
|
self.choose_file_label.setText(settings.get("authentication_file", ""))
|
||||||
|
self.character_to_load.setCurrentText(settings.get("character", ""))
|
||||||
self.pre_layer_slider.setValue(int(settings.get("prelayer", 0)))
|
self.pre_layer_slider.setValue(int(settings.get("prelayer", 0)))
|
||||||
self.use_autolaunch_checkbox.setChecked(settings.get("autolaunch", False))
|
self.use_autolaunch_checkbox.setChecked(settings.get("autolaunch", False))
|
||||||
self.use_network_checkbox.setChecked(settings.get("listen", False))
|
self.use_network_checkbox.setChecked(settings.get("listen", False))
|
||||||
@@ -846,4 +1032,7 @@ if __name__ == "__main__":
|
|||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
main_window = MainWindow()
|
main_window = MainWindow()
|
||||||
main_window.show()
|
main_window.show()
|
||||||
|
if darkdetect.isDark():
|
||||||
|
dark_stylesheet = qdarkstyle.load_stylesheet_pyqt5()
|
||||||
|
app.setStyleSheet(dark_stylesheet)
|
||||||
sys.exit(app.exec_())
|
sys.exit(app.exec_())
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
PyQt5
|
PyQt5
|
||||||
gpustat
|
gpustat
|
||||||
psutil
|
psutil
|
||||||
|
qdarkstyle
|
||||||
|
darkdetect
|
||||||
|
requests
|
||||||
Reference in New Issue
Block a user