From 30adf9da958a5f60341540c540fe68c2d83b0afd Mon Sep 17 00:00:00 2001 From: XHPlus Date: Mon, 8 Jun 2026 12:51:15 +0800 Subject: [PATCH] feat(platform): discover out-of-tree backends via entry points MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a `lightx2v.platform_plugins` entry-point scan to `set_ai_device()` so a chip backend can be shipped as a separate pip package and registered at runtime without editing this repo — the same out-of-tree plugin model vLLM uses. The scan runs before `init_ai_device()` (so a plugin-provided device is visible to the lookup) and before `lightx2v_platform.ops` is imported, i.e. before `registry_factory` snapshots the platform registries via `merge()`. That ordering is what lets plugin registrations reach the framework-facing registries. Safe by construction: no-op when no plugins are installed, in-tree platforms unchanged, a failing plugin is logged and skipped, and no new dependency (`importlib.metadata` is stdlib). Co-Authored-By: Claude Opus 4.8 --- lightx2v_platform/README.md | 37 ++++++++++++++++++++++++++++ lightx2v_platform/set_ai_device.py | 39 ++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/lightx2v_platform/README.md b/lightx2v_platform/README.md index cf2adf1be..fdfa2fc17 100755 --- a/lightx2v_platform/README.md +++ b/lightx2v_platform/README.md @@ -18,3 +18,40 @@ Currently supported backends include: For the corresponding Docker environments, see: https://github.com/ModelTC/LightX2V/tree/main/dockerfiles/platforms For the corresponding usage scripts, see: https://github.com/ModelTC/LightX2V/tree/main/scripts/platforms + +## Out-of-tree platform plugins + +Besides in-tree backends, a chip backend can be shipped as a separate +pip-installable package and discovered at runtime via entry points — no edits to +this repository required. + +A plugin package declares an entry point in the `lightx2v.platform_plugins` +group: + +```toml +# plugin package's pyproject.toml +[project.entry-points."lightx2v.platform_plugins"] +my_backend = "my_backend_pkg:register" +``` + +The referenced callable registers a `Device` class into +`PLATFORM_DEVICE_REGISTER` and its operators into the `PLATFORM_*` op registries: + +```python +# my_backend_pkg/__init__.py +def register(): + from . import device # @PLATFORM_DEVICE_REGISTER("my_backend") + from .ops import register_ops + register_ops() +``` + +`set_ai_device()` scans this group before initialising the device and before the +op registries are imported, so plugin registrations reach the framework. Then: + +```bash +pip install my-backend-package +PLATFORM=my_backend python lightx2v/infer.py ... +``` + +When no plugins are installed this scan is a no-op, and a plugin that fails to +load is logged and skipped rather than aborting device setup. diff --git a/lightx2v_platform/set_ai_device.py b/lightx2v_platform/set_ai_device.py index b0a4f32f3..2842463fe 100644 --- a/lightx2v_platform/set_ai_device.py +++ b/lightx2v_platform/set_ai_device.py @@ -1,10 +1,49 @@ import os +from loguru import logger + from lightx2v_platform import * +def _load_platform_plugins(): + """Discover out-of-tree platform backends via entry points. + + Third-party packages register under the ``lightx2v.platform_plugins`` entry + point group. Each entry point is a zero-arg callable that registers its + Device class into ``PLATFORM_DEVICE_REGISTER`` and its ops into the + ``PLATFORM_*`` op registries. + + This runs before ``init_ai_device`` (so a plugin-provided device is visible + to the lookup) and before ``lightx2v_platform.ops`` is imported, i.e. before + ``lightx2v.utils.registry_factory`` snapshots the platform registries via + ``merge()``. That ordering is what makes plugin registrations reach the + framework-facing registries. + + No effect when no plugins are installed; a failing plugin is logged and + skipped rather than aborting device setup. + """ + try: + from importlib.metadata import entry_points + except Exception: # pragma: no cover - importlib.metadata is stdlib on 3.8+ + return + + try: + eps = entry_points(group="lightx2v.platform_plugins") + except TypeError: + # importlib.metadata < 3.10 returns a dict-like mapping. + eps = entry_points().get("lightx2v.platform_plugins", []) + + for ep in eps: + try: + ep.load()() + logger.info(f"Loaded LightX2V platform plugin: {ep.name}") + except Exception as e: + logger.warning(f"Failed to load platform plugin '{ep.name}': {e}") + + def set_ai_device(): platform = os.getenv("PLATFORM", "cuda") + _load_platform_plugins() init_ai_device(platform) check_ai_device(platform)