From c8babbd6e10ebbf83081cf4450898f249254bf18 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sun, 18 Aug 2024 13:30:45 -0700 Subject: [PATCH] feat(core): add update checking support - add update checking support with AUTOGGUF_CHECK_UPDATE (enabled) env variable - fix setup.py - add localization keys for update checking - update version to v1.7.2 in Localizations.py - formatting changes --- setup.py | 24 +++++------ src/AutoGGUF.py | 38 ++++++++++++++++ src/Localizations.py | 9 +++- src/main.py | 100 ++++++++++++++++++++++--------------------- 4 files changed, 107 insertions(+), 64 deletions(-) diff --git a/setup.py b/setup.py index 4104199..249242a 100644 --- a/setup.py +++ b/setup.py @@ -1,21 +1,17 @@ from setuptools import setup -with open('requirements.txt') as f: +with open("requirements.txt") as f: required = f.read().splitlines() setup( - name='AutoGGUF', - version='v1.7.1', - packages=[''], - url='https://github.com/leafspark/AutoGGUF', - license='apache-2.0', - author='leafspark', - author_email='', - description='automatically quant GGUF models', + name="AutoGGUF", + version="v1.7.1", + packages=[""], + url="https://github.com/leafspark/AutoGGUF", + license="apache-2.0", + author="leafspark", + author_email="", + description="automatically quant GGUF models", install_requires=required, - entry_points={ - 'console_scripts': [ - 'autogguf-gui = src.main' - ] - } + entry_points={"console_scripts": ["autogguf-gui = main:main"]}, ) diff --git a/src/AutoGGUF.py b/src/AutoGGUF.py index b521efa..b591d85 100644 --- a/src/AutoGGUF.py +++ b/src/AutoGGUF.py @@ -28,6 +28,7 @@ import ui_update import lora_conversion import utils +import requests class AutoGGUF(QMainWindow): @@ -202,21 +203,26 @@ def __init__(self): self.release_combo = QComboBox() self.refresh_releases_button = QPushButton(REFRESH_RELEASES) self.refresh_releases_button.clicked.connect(self.refresh_releases) + release_layout = QHBoxLayout() release_layout.addWidget(self.release_combo) release_layout.addWidget(self.refresh_releases_button) download_layout.addRow(SELECT_RELEASE, release_layout) + self.asset_combo = QComboBox() self.asset_combo.currentIndexChanged.connect(self.update_cuda_option) download_layout.addRow(SELECT_ASSET, self.asset_combo) + self.cuda_extract_checkbox = QCheckBox(EXTRACT_CUDA_FILES) self.cuda_extract_checkbox.setVisible(False) download_layout.addRow(self.cuda_extract_checkbox) + self.cuda_backend_label = QLabel(SELECT_CUDA_BACKEND) self.cuda_backend_label.setVisible(False) self.backend_combo_cuda = QComboBox() self.backend_combo_cuda.setVisible(False) download_layout.addRow(self.cuda_backend_label, self.backend_combo_cuda) + self.download_progress = QProgressBar() self.download_button = QPushButton(DOWNLOAD) self.download_button.clicked.connect(self.download_llama_cpp) @@ -739,6 +745,10 @@ def __init__(self): self.refresh_releases() self.refresh_backends() + if os.environ.get("AUTOGGUF_CHECK_UPDATE", "").lower() == "enabled": + self.logger.info(CHECKING_FOR_UPDATES) + self.check_for_updates() + # Load theme based on environment variable theme_path = os.environ.get("AUTOGGUF_THEME") if theme_path: @@ -762,6 +772,34 @@ def __init__(self): self.load_models() self.logger.info(AUTOGGUF_INITIALIZATION_COMPLETE) + def check_for_updates(self): + try: + response = requests.get( + "https://api.github.com/repos/leafspark/AutoGGUF/releases/latest" + ) + response.raise_for_status() # Raise an exception for bad status codes + + latest_release = response.json() + latest_version = latest_release["tag_name"].replace("v", "") + + if latest_version > AUTOGGUF_VERSION.replace("v", ""): + self.prompt_for_update(latest_release) + except requests.exceptions.RequestException as e: + self.logger.warning(f"{ERROR_CHECKING_FOR_UPDATES} {e}") + + def prompt_for_update(self, release): + update_message = QMessageBox() + update_message.setIcon(QMessageBox.Information) + update_message.setWindowTitle(UPDATE_AVAILABLE) + update_message.setText(NEW_VERSION_AVAILABLE.format(release["tag_name"])) + update_message.setInformativeText(DOWNLOAD_NEW_VERSION) + update_message.addButton(QMessageBox.StandardButton.Yes) + update_message.addButton(QMessageBox.StandardButton.No) + update_message.setDefaultButton(QMessageBox.StandardButton.Yes) + + if update_message.exec() == QMessageBox.StandardButton.Yes: + QDesktopServices.openUrl(QUrl(release["html_url"])) + def keyPressEvent(self, event): if event.modifiers() == Qt.ControlModifier: if ( diff --git a/src/Localizations.py b/src/Localizations.py index 37dcd1e..752b11e 100644 --- a/src/Localizations.py +++ b/src/Localizations.py @@ -1,6 +1,6 @@ import os -AUTOGGUF_VERSION = "v1.7.1" +AUTOGGUF_VERSION = "v1.7.2" class _Localization: @@ -125,6 +125,13 @@ def __init__(self): "Browsing for HuggingFace to GGUF output file" ) + # Update Checking + self.UPDATE_AVAILABLE = "Update Avaliable" + self.NEW_VERSION_AVAILABLE = "A new version is avaliable: {}" + self.DOWNLOAD_NEW_VERSION = "Download?" + self.ERROR_CHECKING_FOR_UPDATES = "Error checking for updates:" + self.CHECKING_FOR_UPDATES = "Checking for updates" + # General Messages self.ERROR = "Error" self.WARNING = "Warning" diff --git a/src/main.py b/src/main.py index 849da85..0226cd2 100644 --- a/src/main.py +++ b/src/main.py @@ -10,52 +10,54 @@ server = Flask(__name__) -@server.route("/v1/models", methods=["GET"]) -def models(): - if window: - return jsonify({"models": window.get_models_data()}) - return jsonify({"models": []}) - - -@server.route("/v1/tasks", methods=["GET"]) -def tasks(): - if window: - return jsonify({"tasks": window.get_tasks_data()}) - return jsonify({"tasks": []}) - - -@server.route("/v1/health", methods=["GET"]) -def ping(): - return jsonify({"status": "alive"}) - - -@server.route("/v1/backends", methods=["GET"]) -def get_backends(): - backends = [] - for i in range(window.backend_combo.count()): - backends.append( - { - "name": window.backend_combo.itemText(i), - "path": window.backend_combo.itemData(i), - } - ) - return jsonify({"backends": backends}) - - -def run_flask(): - if os.environ.get("AUTOGGUF_SERVER", "").lower() == "true": - server.run( - host="0.0.0.0", - port=int(os.environ.get("AUTOGGUF_SERVER_PORT", 5000)), - debug=False, - use_reloader=False, - ) - - -app = QApplication(sys.argv) -window = AutoGGUF() -window.show() -# Start Flask in a separate thread after a short delay -timer = QTimer() -timer.singleShot(100, lambda: threading.Thread(target=run_flask, daemon=True).start()) -sys.exit(app.exec()) +def main(): + @server.route("/v1/models", methods=["GET"]) + def models(): + if window: + return jsonify({"models": window.get_models_data()}) + return jsonify({"models": []}) + + @server.route("/v1/tasks", methods=["GET"]) + def tasks(): + if window: + return jsonify({"tasks": window.get_tasks_data()}) + return jsonify({"tasks": []}) + + @server.route("/v1/health", methods=["GET"]) + def ping(): + return jsonify({"status": "alive"}) + + @server.route("/v1/backends", methods=["GET"]) + def get_backends(): + backends = [] + for i in range(window.backend_combo.count()): + backends.append( + { + "name": window.backend_combo.itemText(i), + "path": window.backend_combo.itemData(i), + } + ) + return jsonify({"backends": backends}) + + def run_flask(): + if os.environ.get("AUTOGGUF_SERVER", "").lower() == "true": + server.run( + host="0.0.0.0", + port=int(os.environ.get("AUTOGGUF_SERVER_PORT", 5000)), + debug=False, + use_reloader=False, + ) + + app = QApplication(sys.argv) + window = AutoGGUF() + window.show() + # Start Flask in a separate thread after a short delay + timer = QTimer() + timer.singleShot( + 100, lambda: threading.Thread(target=run_flask, daemon=True).start() + ) + sys.exit(app.exec()) + + +if __name__ == "__main__": + main()