|
|
|
@@ -1,7 +1,9 @@
|
|
|
|
|
import sys, gpustat, os, json, subprocess, platform, psutil, urllib.request, re
|
|
|
|
|
from PyQt5.QtWidgets import QApplication, QMessageBox, QProgressBar, QMainWindow, QLabel, QVBoxLayout, QComboBox, QSlider, QCheckBox, QLineEdit, QFileDialog, QPushButton, QWidget, QListWidget, QListWidgetItem, QToolTip, QGridLayout, QRadioButton, QFrame, QDialog
|
|
|
|
|
import sys, gpustat, os, json, subprocess, platform, psutil, re, requests, darkdetect, qdarkstyle
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
version = "1.3.1"
|
|
|
|
|
|
|
|
|
|
profiles_folder = "./profiles"
|
|
|
|
|
os.makedirs(profiles_folder, exist_ok=True)
|
|
|
|
|
model_folder = "./text-generation-webui/models"
|
|
|
|
@@ -67,16 +69,61 @@ class MainWindow(QMainWindow):
|
|
|
|
|
self.init_ui()
|
|
|
|
|
self.load_settings()
|
|
|
|
|
self.set_ram_slider_max()
|
|
|
|
|
self.update_check()
|
|
|
|
|
|
|
|
|
|
def init_ui(self):
|
|
|
|
|
self.setWindowTitle('StartUI for oobabooga webui')
|
|
|
|
|
#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.setColumnMinimumWidth(3, 30)
|
|
|
|
|
|
|
|
|
|
# Model Dropdown
|
|
|
|
|
# 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.append("none")
|
|
|
|
|
self.model_dropdown = QComboBox()
|
|
|
|
|
self.model_dropdown.addItems(model_folders)
|
|
|
|
|
layout.addWidget(QLabel("Choose Model:"))
|
|
|
|
@@ -93,7 +140,7 @@ class MainWindow(QMainWindow):
|
|
|
|
|
self.reload_model_button.setToolTip("Reloads the Names in the Models Folder")
|
|
|
|
|
self.reload_model_button.clicked.connect(self.reload_models)
|
|
|
|
|
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
|
|
|
|
|
self.wbit_dropdown = QComboBox()
|
|
|
|
@@ -107,7 +154,7 @@ class MainWindow(QMainWindow):
|
|
|
|
|
self.gsize_dropdown.addItems(["32", "64", "128", "1024", "none"])
|
|
|
|
|
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")
|
|
|
|
|
layout.addWidget(self.gsize_dropdown, 6, 1)
|
|
|
|
|
layout.addWidget(self.gsize_dropdown, 6, 1, 1, 2)
|
|
|
|
|
|
|
|
|
|
# Mode Dropdown
|
|
|
|
|
self.mode_dropdown = QComboBox()
|
|
|
|
@@ -119,7 +166,7 @@ class MainWindow(QMainWindow):
|
|
|
|
|
self.update_button = QPushButton("Update oobabooga")
|
|
|
|
|
self.update_button.setToolTip("Starts the Update Routine for the text-generation-webui")
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
# Add horizontal line to seperate the CPU/GPU Settings
|
|
|
|
@@ -414,6 +461,105 @@ class MainWindow(QMainWindow):
|
|
|
|
|
self.load_button.clicked.connect(self.on_load_button_clicked)
|
|
|
|
|
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):
|
|
|
|
|
self.extensions_list.setVisible(state == Qt.Checked)
|
|
|
|
|
|
|
|
|
@@ -598,11 +744,12 @@ class MainWindow(QMainWindow):
|
|
|
|
|
|
|
|
|
|
# Add the chosen model to the command
|
|
|
|
|
chosen_model = self.model_dropdown.currentText()
|
|
|
|
|
if self.model_dropdown.currentText() != "none":
|
|
|
|
|
command += f" --model {chosen_model}"
|
|
|
|
|
|
|
|
|
|
# Add the chosen model type to the command
|
|
|
|
|
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}"
|
|
|
|
|
|
|
|
|
|
# Add loras to the command
|
|
|
|
@@ -610,20 +757,20 @@ class MainWindow(QMainWindow):
|
|
|
|
|
# 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]
|
|
|
|
|
if self.use_lora_checkbox.isChecked():
|
|
|
|
|
if self.use_lora_checkbox.isChecked() and self.model_dropdown.currentText() != "none":
|
|
|
|
|
if loras:
|
|
|
|
|
command += f" --lora {' '.join(loras)}"
|
|
|
|
|
|
|
|
|
|
# Adds wbits to the command, if not "none"
|
|
|
|
|
chosen_wbits = self.wbit_dropdown.currentText()
|
|
|
|
|
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}"
|
|
|
|
|
|
|
|
|
|
# Adds Groupsize to the command, if not "none"
|
|
|
|
|
chosen_gsize = self.gsize_dropdown.currentText()
|
|
|
|
|
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}"
|
|
|
|
|
|
|
|
|
|
# Add the chosen mode to the command (Chat, cai-chat, notebook)
|
|
|
|
@@ -742,7 +889,7 @@ class MainWindow(QMainWindow):
|
|
|
|
|
sys.exit()
|
|
|
|
|
|
|
|
|
|
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):
|
|
|
|
|
with open(profile_file, "r") as file:
|
|
|
|
@@ -846,4 +993,7 @@ if __name__ == "__main__":
|
|
|
|
|
app = QApplication(sys.argv)
|
|
|
|
|
main_window = MainWindow()
|
|
|
|
|
main_window.show()
|
|
|
|
|
if darkdetect.isDark():
|
|
|
|
|
dark_stylesheet = qdarkstyle.load_stylesheet_pyqt5()
|
|
|
|
|
app.setStyleSheet(dark_stylesheet)
|
|
|
|
|
sys.exit(app.exec_())
|