mirror of https://github.com/leafspark/AutoGGUF
feat(core): implement plugins
- add plugins feature using importlib - edit .gitignore - change enabled state of AUTOGGUF_SERVER to "enabled" from "true" for consistency
This commit is contained in:
parent
53ab6a688e
commit
d4be39a22c
|
@ -26,6 +26,11 @@ src/*
|
|||
docs/*
|
||||
!docs/*.py
|
||||
|
||||
# Allow plugins folder and its .py files
|
||||
!plugins/
|
||||
plugins/*
|
||||
!plugins/*.py
|
||||
|
||||
# Allow assets folder, but only .svg, .png, .rc, .css, .iss and .ico files
|
||||
!assets/
|
||||
assets/*
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
class ExamplePlugin:
|
||||
def init(self, autogguf_instance):
|
||||
# This gets called after the plugin is loaded
|
||||
print("Plugin initialized")
|
||||
|
||||
def __data__(self):
|
||||
return {
|
||||
"name": "ExamplePlugin",
|
||||
"description": "This is an example plugin.",
|
||||
"compatible_versions": ["*"],
|
||||
"author": "leafspark",
|
||||
"version": "v1.0.0",
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import json
|
||||
import re
|
||||
import shutil
|
||||
import importlib
|
||||
|
||||
from functools import partial
|
||||
from datetime import datetime
|
||||
|
@ -777,8 +778,87 @@ def __init__(self, args):
|
|||
|
||||
# Load models
|
||||
self.load_models()
|
||||
|
||||
# Load plugins
|
||||
self.plugins = self.load_plugins()
|
||||
self.apply_plugins()
|
||||
|
||||
self.logger.info(AUTOGGUF_INITIALIZATION_COMPLETE)
|
||||
|
||||
def load_plugins(self):
|
||||
plugins = {}
|
||||
plugin_dir = "plugins"
|
||||
|
||||
if not os.path.exists(plugin_dir):
|
||||
self.logger.info(PLUGINS_DIR_NOT_EXIST.format(plugin_dir))
|
||||
return plugins
|
||||
|
||||
if not os.path.isdir(plugin_dir):
|
||||
self.logger.warning(PLUGINS_DIR_NOT_DIRECTORY.format(plugin_dir))
|
||||
return plugins
|
||||
|
||||
for file in os.listdir(plugin_dir):
|
||||
if file.endswith(".py") and not file.endswith(".disabled.py"):
|
||||
name = file[:-3]
|
||||
path = os.path.join(plugin_dir, file)
|
||||
|
||||
try:
|
||||
spec = importlib.util.spec_from_file_location(name, path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
for item_name in dir(module):
|
||||
item = getattr(module, item_name)
|
||||
if isinstance(item, type) and hasattr(item, "__data__"):
|
||||
plugin_instance = item()
|
||||
plugin_data = plugin_instance.__data__()
|
||||
|
||||
compatible_versions = plugin_data.get(
|
||||
"compatible_versions", []
|
||||
)
|
||||
if (
|
||||
"*" in compatible_versions
|
||||
or AUTOGGUF_VERSION in compatible_versions
|
||||
):
|
||||
plugins[name] = {
|
||||
"instance": plugin_instance,
|
||||
"data": plugin_data,
|
||||
}
|
||||
self.logger.info(
|
||||
PLUGIN_LOADED.format(
|
||||
plugin_data["name"], plugin_data["version"]
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.logger.warning(
|
||||
PLUGIN_INCOMPATIBLE.format(
|
||||
plugin_data["name"],
|
||||
plugin_data["version"],
|
||||
AUTOGGUF_VERSION,
|
||||
", ".join(compatible_versions),
|
||||
)
|
||||
)
|
||||
break
|
||||
except Exception as e:
|
||||
self.logger.error(PLUGIN_LOAD_FAILED.format(name, str(e)))
|
||||
|
||||
return plugins
|
||||
|
||||
def apply_plugins(self):
|
||||
if not self.plugins:
|
||||
self.logger.info(NO_PLUGINS_LOADED)
|
||||
return
|
||||
|
||||
for plugin_name, plugin_info in self.plugins.items():
|
||||
plugin_instance = plugin_info["instance"]
|
||||
for attr_name in dir(plugin_instance):
|
||||
if not attr_name.startswith("__") and attr_name != "init":
|
||||
attr_value = getattr(plugin_instance, attr_name)
|
||||
setattr(self, attr_name, attr_value)
|
||||
|
||||
if hasattr(plugin_instance, "init") and callable(plugin_instance.init):
|
||||
plugin_instance.init(self)
|
||||
|
||||
def check_for_updates(self):
|
||||
try:
|
||||
response = requests.get(
|
||||
|
|
|
@ -43,6 +43,18 @@ def __init__(self):
|
|||
"Found {} concatenated file parts. Please concat the files first."
|
||||
)
|
||||
|
||||
# Plugins
|
||||
self.PLUGINS_DIR_NOT_EXIST = (
|
||||
"Plugins directory '{}' does not exist. No plugins will be loaded."
|
||||
)
|
||||
self.PLUGINS_DIR_NOT_DIRECTORY = (
|
||||
"'{}' exists but is not a directory. No plugins will be loaded."
|
||||
)
|
||||
self.PLUGIN_LOADED = "Loaded plugin: {} {}"
|
||||
self.PLUGIN_INCOMPATIBLE = "Plugin {} {} is not compatible with AutoGGUF version {}. Supported versions: {}"
|
||||
self.PLUGIN_LOAD_FAILED = "Failed to load plugin {}: {}"
|
||||
self.NO_PLUGINS_LOADED = "No plugins loaded."
|
||||
|
||||
# GPU Monitoring
|
||||
self.GPU_USAGE = "GPU Usage:"
|
||||
self.GPU_USAGE_FORMAT = "GPU: {:.1f}% | VRAM: {:.1f}% ({} MB / {} MB)"
|
||||
|
|
20
src/main.py
20
src/main.py
|
@ -39,8 +39,26 @@ def get_backends():
|
|||
)
|
||||
return jsonify({"backends": backends})
|
||||
|
||||
@server.route("/v1/plugins", methods=["GET"])
|
||||
def get_plugins():
|
||||
if window:
|
||||
return jsonify(
|
||||
{
|
||||
"plugins": [
|
||||
{
|
||||
"name": plugin_data["data"]["name"],
|
||||
"version": plugin_data["data"]["version"],
|
||||
"description": plugin_data["data"]["description"],
|
||||
"author": plugin_data["data"]["author"],
|
||||
}
|
||||
for plugin_data in window.plugins.values()
|
||||
]
|
||||
}
|
||||
)
|
||||
return jsonify({"plugins": []})
|
||||
|
||||
def run_flask():
|
||||
if os.environ.get("AUTOGGUF_SERVER", "").lower() == "true":
|
||||
if os.environ.get("AUTOGGUF_SERVER", "").lower() == "enabled":
|
||||
server.run(
|
||||
host="0.0.0.0",
|
||||
port=int(os.environ.get("AUTOGGUF_SERVER_PORT", 5000)),
|
||||
|
|
Loading…
Reference in New Issue