[add] basic plugin support
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
5afd2bb498
commit
34a602edc3
@ -3,6 +3,7 @@ import click
|
||||
import signal
|
||||
import sys
|
||||
from importlib.metadata import version
|
||||
from minyma.plugin import PluginLoader
|
||||
from minyma.oai import OpenAIConnector
|
||||
from minyma.vdb import ChromaDB
|
||||
from flask import Flask
|
||||
@ -15,7 +16,7 @@ def signal_handler(sig, frame):
|
||||
|
||||
|
||||
def create_app():
|
||||
global oai, vdb
|
||||
global oai, vdb, pman
|
||||
|
||||
from minyma.config import Config
|
||||
import minyma.api.common as api_common
|
||||
@ -24,6 +25,7 @@ def create_app():
|
||||
app = Flask(__name__)
|
||||
vdb = ChromaDB(path.join(Config.DATA_PATH, "chroma"))
|
||||
oai = OpenAIConnector(Config.OPENAI_API_KEY, vdb)
|
||||
pman = PluginLoader()
|
||||
|
||||
app.register_blueprint(api_common.bp)
|
||||
app.register_blueprint(api_v1.bp)
|
||||
|
86
minyma/plugin.py
Normal file
86
minyma/plugin.py
Normal file
@ -0,0 +1,86 @@
|
||||
import inspect
|
||||
import os
|
||||
import importlib.util
|
||||
|
||||
TYPE_DEFS = {str:"string"}
|
||||
|
||||
class MinymaPlugin:
|
||||
pass
|
||||
|
||||
class PluginLoader:
|
||||
def __init__(self):
|
||||
self.plugins = self.get_plugins()
|
||||
self.definitions = self.derive_function_definitions()
|
||||
print(self.definitions)
|
||||
|
||||
|
||||
def derive_function_definitions(self):
|
||||
"""Dynamically generate function definitions"""
|
||||
function_definitions = []
|
||||
|
||||
for plugin in self.plugins:
|
||||
plugin_name = plugin.name
|
||||
|
||||
for method_obj in plugin.functions:
|
||||
method_name = method_obj.__name__
|
||||
signature = inspect.signature(method_obj)
|
||||
parameters = list(signature.parameters.values())
|
||||
|
||||
# Extract Parameter Information
|
||||
params_info = {}
|
||||
for param in parameters:
|
||||
param_name = param.name
|
||||
param_type = param.annotation
|
||||
params_info[param_name] = {"type": TYPE_DEFS[param_type]}
|
||||
|
||||
# Store Function Information
|
||||
method_info = {
|
||||
"name": "%s_%s" %(plugin_name, method_name),
|
||||
"description": inspect.getdoc(method_obj),
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": params_info
|
||||
}
|
||||
}
|
||||
function_definitions.append(method_info)
|
||||
|
||||
return function_definitions
|
||||
|
||||
|
||||
def get_plugins(self):
|
||||
"""Dynamically load plugins"""
|
||||
# Derive Plugin Folder
|
||||
loader_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
plugin_folder = os.path.join(loader_dir, "plugins")
|
||||
|
||||
# Find Minyma Plugins
|
||||
plugin_classes = []
|
||||
for filename in os.listdir(plugin_folder):
|
||||
|
||||
# Exclude Files
|
||||
if not filename.endswith(".py") or filename == "__init__.py":
|
||||
continue
|
||||
|
||||
# Derive Module Path
|
||||
module_name = os.path.splitext(filename)[0]
|
||||
module_path = os.path.join(plugin_folder, filename)
|
||||
|
||||
# Load Module Dynamically
|
||||
spec = importlib.util.spec_from_file_location(module_name, module_path)
|
||||
if spec is None or spec.loader is None:
|
||||
raise ImportError("Unable to dynamically load plugin - %s" % filename)
|
||||
|
||||
# Load & Exec Module
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
# Only Process MinymaPlugin SubClasses
|
||||
for _, member in inspect.getmembers(module):
|
||||
if inspect.isclass(member) and issubclass(member, MinymaPlugin) and member != MinymaPlugin:
|
||||
plugin_classes.append(member)
|
||||
|
||||
# Instantiate Plugins
|
||||
plugins = []
|
||||
for cls in plugin_classes:
|
||||
plugins.append(cls())
|
||||
return plugins
|
3
minyma/plugins/README.md
Normal file
3
minyma/plugins/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Plugins
|
||||
|
||||
These are plugins that provide OpenAI with functions. Each plugin can define multiple plugins. The plugin loader will automatically derive the function definition. Each function will have the plugin name prepended.
|
21
minyma/plugins/duckduckgo.py
Normal file
21
minyma/plugins/duckduckgo.py
Normal file
@ -0,0 +1,21 @@
|
||||
from minyma.plugin import MinymaPlugin
|
||||
|
||||
class DuckDuckGoPlugin(MinymaPlugin):
|
||||
"""Search DuckDuckGo"""
|
||||
|
||||
def __init__(self):
|
||||
self.name = "duck_duck_go"
|
||||
self.functions = [self.search]
|
||||
|
||||
def search(self, query: str):
|
||||
"""Search DuckDuckGo"""
|
||||
|
||||
"""
|
||||
TODO:
|
||||
1. API Query
|
||||
2. Parse (BeautifulSoup?)
|
||||
3. Return top 10 (Title & Blurb?)
|
||||
|
||||
ENDPOINT: https://html.duckduckgo.com/html/?q=%s
|
||||
"""
|
||||
pass
|
Loading…
Reference in New Issue
Block a user