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/*
|
||||||
!docs/*.py
|
!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
|
# Allow assets folder, but only .svg, .png, .rc, .css, .iss and .ico files
|
||||||
!assets/
|
!assets/
|
||||||
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 json
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
import importlib
|
||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -777,8 +778,87 @@ def __init__(self, args):
|
||||||
|
|
||||||
# Load models
|
# Load models
|
||||||
self.load_models()
|
self.load_models()
|
||||||
|
|
||||||
|
# Load plugins
|
||||||
|
self.plugins = self.load_plugins()
|
||||||
|
self.apply_plugins()
|
||||||
|
|
||||||
self.logger.info(AUTOGGUF_INITIALIZATION_COMPLETE)
|
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):
|
def check_for_updates(self):
|
||||||
try:
|
try:
|
||||||
response = requests.get(
|
response = requests.get(
|
||||||
|
|
|
@ -43,6 +43,18 @@ def __init__(self):
|
||||||
"Found {} concatenated file parts. Please concat the files first."
|
"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
|
# GPU Monitoring
|
||||||
self.GPU_USAGE = "GPU Usage:"
|
self.GPU_USAGE = "GPU Usage:"
|
||||||
self.GPU_USAGE_FORMAT = "GPU: {:.1f}% | VRAM: {:.1f}% ({} MB / {} MB)"
|
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})
|
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():
|
def run_flask():
|
||||||
if os.environ.get("AUTOGGUF_SERVER", "").lower() == "true":
|
if os.environ.get("AUTOGGUF_SERVER", "").lower() == "enabled":
|
||||||
server.run(
|
server.run(
|
||||||
host="0.0.0.0",
|
host="0.0.0.0",
|
||||||
port=int(os.environ.get("AUTOGGUF_SERVER_PORT", 5000)),
|
port=int(os.environ.get("AUTOGGUF_SERVER_PORT", 5000)),
|
||||||
|
|
Loading…
Reference in New Issue