Plugin System

扩展层:插件化生态与动态反射装载

全面解析 plugins 目录、plugin_llm.py 适配与 memory_manager.py 插件实例化路径
Python 插件动态发现生命周期
📊 图 7-1:Python 插件动态扫描、Import Hook 依赖解析与 ABCs 契约映射图

🧩 1. Edges 设计与 plugins/ 目录职责

为贯彻核心“Narrow Waist(极窄腰部)”的设计准则,Hermes 将所有外围的大模型推理服务对接、长期记忆管理以及高级业务完全以插件(Plugins)形式实现,隔离在 plugins/ 目录下:

  • plugins/memory/:第三方长期记忆库扩展(如 oometa-memoshonchosupermemory)。
  • plugins/model-providers/:第三方大模型服务 API 适配器插件(如 openroutermoonshot)。
  • plugins/context_engine/:特定的上下文引用与检索生成插件。

⚙️ 2. 插件装载生命周期的四大阶段

如插件生命周期图所示,系统在运行时不需要在核心代码里写死任何插件类,而是通过动态扫描自适应反射拉起:

  1. Stage 1: Plugin Scanning & Metadata Discovery(扫描阶段): 在项目启动时,系统扫描 plugins/ 路径以及用户主目录下 ~/.hermes/plugins/ 内的动态模块,读取其中的 __init__.py 声明,确认插件类型(如 memorymodel_provider)。
  2. Stage 2: Import Hook Registry & Dependency Management(依赖解析): 动态注册 Python 导入挂钩(Import Hook),检查插件环境依赖包(如 `redis` 或特定 SDK)。若依赖缺失,则抛出警告,并在内存中标记为不可用,防止主进程崩溃。
  3. Stage 3: Base Abstract Classes Mapping & Validation(基类契约): 提取并校验插件是否实现了预设的抽象基类(ABCs,如 MemoryProviderABCModelProviderABC)。检查抽象方法签名与参数类型是否完全一致,若不合规,则报 Validation 错误。
  4. Stage 4: Plugin Registration & Provider Types(注册实例化): 在确认验证通过后,将插件以键值对存入相应的管理器(如 MemoryManagerModelRegistry)中。当用户在 config.yaml 中启用时,直接实例化插件类提供支持。
插件数据同步与一致性
📊 图 7-2:插件长期记忆数据同步与事务锁一致性时序图

🧠 3. 核心加载代码剖析

📦 插件大模型接口适配 (agent/plugin_llm.py)

agent/plugin_llm.py 中,系统对外来大模型推理插件进行了统一的抽象化包装。不论大模型底层库是基于 requests 直连还是基于私有 Python SDK,大模型插件只需暴露一个统一的 generate_response() 签名,plugin_llm.py 会自动对输出的 Token 碎片和 Reasoning 加密段进行兼容解析。

💾 记忆提供者注册挂载 (agent/memory_manager.py)

agent/memory_manager.py 中,记忆管理器类 MemoryManager 利用反射自适应装配记忆插件:

# agent/memory_manager.py 动态加载实现片断
from agent.memory_provider import MemoryProviderABC

def register_memory_plugin(self, provider_name: str):
    # 根据配置中的 provider_name 动态导入对应的插件类
    try:
        module_path = f"plugins.memory.{provider_name}"
        module = importlib.import_module(module_path)
        
        # 反射寻找实现了抽象类 MemoryProviderABC 的具体子类
        for name, obj in inspect.getmembers(module):
            if inspect.isclass(obj) and issubclass(obj, MemoryProviderABC) and obj is not MemoryProviderABC:
                self._tool_to_provider[provider_name] = obj()
                logger.info(f"Successfully mounted memory plugin: {provider_name}")
                return
    except Exception as e:
         logger.warning(f"Memory provider '{provider_name}' initialize failed: {e}")

这一设计真正实现了解耦:新开发者只需开发实现了 MemoryProviderABC 的 Python 模块,往 plugins/memory/ 中一丢,便能在无侵入修改核心代码的情况下,动态挂载给 AIAgent 使用。