🔧 fix(getters.py): add import statement for PluginService in getters.py to fix import error
✨ feat(plugins/base.py): add BasePlugin class with initialize, teardown, and get methods to serve as base class for plugins ✨ feat(plugins/factory.py): add PluginServiceFactory class to create PluginService instance and load plugins ✨ feat(plugins/langfuse.py): add LangfusePlugin class with initialize, teardown, and get methods to serve as a plugin for Langfuse ✨ feat(plugins/service.py): add PluginService class to manage plugins, load plugins, register plugins, get plugins, and teardown plugins ✨ feat(schema.py): add PLUGIN_SERVICE to ServiceType enum to support plugin service 🔧 fix(settings/base.py): add PLUGIN_DIR optional setting to support specifying plugin directory 🔧 fix(utils.py): add import statement for plugins_factory in utils.py to fix import error
This commit is contained in:
parent
0a4de7ca94
commit
faa2a79c2b
8 changed files with 100 additions and 0 deletions
|
|
@ -9,9 +9,14 @@ if TYPE_CHECKING:
|
|||
from langflow.services.session.service import SessionService
|
||||
from langflow.services.task.service import TaskService
|
||||
from langflow.services.chat.service import ChatService
|
||||
from langflow.services.plugins.service import PluginService
|
||||
from sqlmodel import Session
|
||||
|
||||
|
||||
def get_plugins_service() -> "PluginService":
|
||||
return service_manager.get(ServiceType.PLUGIN_SERVICE)
|
||||
|
||||
|
||||
def get_settings_service() -> "SettingsService":
|
||||
try:
|
||||
return service_manager.get(ServiceType.SETTINGS_SERVICE)
|
||||
|
|
|
|||
12
src/backend/langflow/services/plugins/base.py
Normal file
12
src/backend/langflow/services/plugins/base.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
from typing import Any
|
||||
|
||||
|
||||
class BasePlugin:
|
||||
def initialize(self):
|
||||
pass
|
||||
|
||||
def teardown(self):
|
||||
pass
|
||||
|
||||
def get(self) -> Any:
|
||||
pass
|
||||
16
src/backend/langflow/services/plugins/factory.py
Normal file
16
src/backend/langflow/services/plugins/factory.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
from typing import TYPE_CHECKING
|
||||
from langflow.services.plugins.service import PluginService
|
||||
from langflow.services.factory import ServiceFactory
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from langflow.services.settings.service import SettingsService
|
||||
|
||||
|
||||
class PluginServiceFactory(ServiceFactory):
|
||||
def __init__(self):
|
||||
super().__init__(PluginService)
|
||||
|
||||
def create(self, settings_service: "SettingsService"):
|
||||
service = PluginService(settings_service)
|
||||
service.load_plugins()
|
||||
return service
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
from langflow.services.getters import get_settings_service
|
||||
from langflow.services.plugins.base import BasePlugin
|
||||
from langflow.utils.logger import logger
|
||||
|
||||
### Temporary implementation
|
||||
|
|
@ -52,3 +53,14 @@ class LangfuseInstance:
|
|||
if cls._instance is not None:
|
||||
cls._instance.flush()
|
||||
cls._instance = None
|
||||
|
||||
|
||||
class LangfusePlugin(BasePlugin):
|
||||
def initialize(self):
|
||||
LangfuseInstance.create()
|
||||
|
||||
def teardown(self):
|
||||
LangfuseInstance.teardown()
|
||||
|
||||
def get(self):
|
||||
return LangfuseInstance.get()
|
||||
|
|
|
|||
50
src/backend/langflow/services/plugins/service.py
Normal file
50
src/backend/langflow/services/plugins/service.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import importlib
|
||||
import inspect
|
||||
import os
|
||||
from langflow.services.base import Service
|
||||
from langflow.services.plugins.base import BasePlugin
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from langflow.services.settings.service import SettingsService
|
||||
|
||||
|
||||
class PluginService(Service):
|
||||
name = "plugin_service"
|
||||
|
||||
def __init__(self, settings_service: "SettingsService"):
|
||||
self.plugins = {}
|
||||
plugin_dir = settings_service.settings.PLUGIN_DIR
|
||||
self.plugin_dir = plugin_dir or os.path.dirname(__file__)
|
||||
|
||||
def load_plugins(self):
|
||||
base_files = ["base.py", "service.py", "factory.py", "__init__.py"]
|
||||
for module in os.listdir(self.plugin_dir):
|
||||
if module.endswith(".py") and module not in base_files:
|
||||
plugin_name = module[:-3]
|
||||
module_path = f"{self.plugin_dir}.{plugin_name}"
|
||||
mod = importlib.import_module(module_path)
|
||||
for attr_name in dir(mod):
|
||||
attr = getattr(mod, attr_name)
|
||||
if (
|
||||
inspect.isclass(attr)
|
||||
and issubclass(attr, BasePlugin)
|
||||
and attr is not BasePlugin
|
||||
):
|
||||
self.register_plugin(plugin_name, attr())
|
||||
|
||||
def register_plugin(self, plugin_name, plugin_instance):
|
||||
self.plugins[plugin_name] = plugin_instance
|
||||
plugin_instance.initialize()
|
||||
|
||||
def get_plugin(self, plugin_name) -> Union[BasePlugin, None]:
|
||||
return self.plugins.get(plugin_name)
|
||||
|
||||
def get(self, plugin_name):
|
||||
if plugin := self.get_plugin(plugin_name):
|
||||
return plugin.get()
|
||||
return None
|
||||
|
||||
def teardown(self):
|
||||
for plugin in self.plugins.values():
|
||||
plugin.teardown()
|
||||
|
|
@ -14,3 +14,4 @@ class ServiceType(str, Enum):
|
|||
CHAT_SERVICE = "chat_service"
|
||||
SESSION_SERVICE = "session_service"
|
||||
TASK_SERVICE = "task_service"
|
||||
PLUGIN_SERVICE = "plugin_service"
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ class Settings(BaseSettings):
|
|||
REDIS_DB: int = 0
|
||||
REDIS_CACHE_EXPIRE: int = 3600
|
||||
|
||||
PLUGIN_DIR: Optional[str] = None
|
||||
|
||||
LANGFUSE_SECRET_KEY: Optional[str] = None
|
||||
LANGFUSE_PUBLIC_KEY: Optional[str] = None
|
||||
LANGFUSE_HOST: Optional[str] = None
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ def get_factories_and_deps():
|
|||
from langflow.services.auth import factory as auth_factory
|
||||
from langflow.services.task import factory as task_factory
|
||||
from langflow.services.session import factory as session_service_factory # type: ignore
|
||||
from langflow.services.plugins import factory as plugins_factory
|
||||
|
||||
return [
|
||||
(settings_factory.SettingsServiceFactory(), []),
|
||||
|
|
@ -40,6 +41,7 @@ def get_factories_and_deps():
|
|||
session_service_factory.SessionServiceFactory(),
|
||||
[ServiceType.CACHE_SERVICE],
|
||||
),
|
||||
(plugins_factory.PluginServiceFactory(), [ServiceType.SETTINGS_SERVICE]),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue