diff --git a/requirements.txt b/requirements.txt index 79c28ce..3dd688b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,5 @@ torch~=1.13.1 sentencepiece~=0.2.0 PyYAML~=6.0.2 pynvml~=11.5.3 -PySide6~=6.7.2 \ No newline at end of file +PySide6~=6.7.2 +flask~=3.0.3 \ No newline at end of file diff --git a/src/AutoGGUF.py b/src/AutoGGUF.py index 8b0e0c2..029f855 100644 --- a/src/AutoGGUF.py +++ b/src/AutoGGUF.py @@ -1,7 +1,6 @@ import json import re import shutil -import sys from datetime import datetime import psutil @@ -9,15 +8,15 @@ from PySide6.QtCore import * from PySide6.QtGui import * from PySide6.QtWidgets import * - +from flask import Flask, jsonify from DownloadThread import DownloadThread +from GPUMonitor import GPUMonitor from KVOverrideEntry import KVOverrideEntry from Logger import Logger from ModelInfoDialog import ModelInfoDialog from QuantizationThread import QuantizationThread from TaskListItem import TaskListItem -from GPUMonitor import GPUMonitor from error_handling import show_error, handle_error from imports_and_globals import ensure_directory, open_file_safe, resource_path from localizations import * @@ -655,7 +654,6 @@ def __init__(self): # Load models self.load_models() - self.logger.info(AUTOGGUF_INITIALIZATION_COMPLETE) def refresh_backends(self): @@ -1751,6 +1749,38 @@ def browse_imatrix_output(self): if output_file: self.imatrix_output.setText(os.path.abspath(output_file)) + def get_models_data(self): + models = [] + root = self.model_tree.invisibleRootItem() + child_count = root.childCount() + for i in range(child_count): + item = root.child(i) + model_name = item.text(0) + model_type = "sharded" if "sharded" in model_name.lower() else "single" + model_path = item.data(0, Qt.ItemDataRole.UserRole) + models.append({"name": model_name, "type": model_type, "path": model_path}) + return models + + def get_tasks_data(self): + tasks = [] + for i in range(self.task_list.count()): + item = self.task_list.item(i) + task_widget = self.task_list.itemWidget(item) + if task_widget: + tasks.append( + { + "name": task_widget.task_name, + "status": task_widget.status, + "progress": ( + task_widget.progress_bar.value() + if hasattr(task_widget, "progress_bar") + else 0 + ), + "log_file": task_widget.log_file, + } + ) + return tasks + def generate_imatrix(self): self.logger.info(STARTING_IMATRIX_GENERATION) try: @@ -1832,10 +1862,3 @@ def closeEvent(self, event: QCloseEvent): else: event.accept() self.logger.info(APPLICATION_CLOSED) - - -if __name__ == "__main__": - app = QApplication(sys.argv) - window = AutoGGUF() - window.show() - sys.exit(app.exec()) diff --git a/src/main.py b/src/main.py index 65d07ae..c509410 100644 --- a/src/main.py +++ b/src/main.py @@ -1,9 +1,54 @@ import sys +import threading + +from PySide6.QtCore import QTimer from PySide6.QtWidgets import QApplication from AutoGGUF import AutoGGUF +from flask import Flask, jsonify -if __name__ == "__main__": - app = QApplication(sys.argv) - window = AutoGGUF() - window.show() - sys.exit(app.exec()) +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(): + server.run(host="0.0.0.0", 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())