Files
2026-07-13 12:08:54 +08:00

67 lines
2.4 KiB
Python

"""Third-party parser engine discovery (``lightrag.parsers`` entry points).
A third-party package exposes parser engines by declaring an entry point in
the ``lightrag.parsers`` group::
# pyproject.toml of the third-party package
[project.entry-points."lightrag.parsers"]
myengine = "my_pkg.lightrag_plugin:register"
Each entry point must resolve to a **zero-argument callable** that performs
its own :func:`lightrag.parser.registry.register_parser` call(s). The
callable should be import-cheap: defer the parser implementation import to
the ``ParserSpec.impl`` string (the registry already loads it lazily).
:func:`load_third_party_parsers` is invoked once per process by both
entrypoints that drive parsers — the API server (``create_app``, before
routing-rule validation so ``LIGHTRAG_PARSER`` may reference third-party
engine names) and the debug CLI (``lightrag.parser.cli.main``, before
``--engine`` choices are built). Library users embedding LightRAG directly
can call it themselves before constructing pipelines.
See ``docs/ThirdPartyParser-zh.md`` for the full plugin authoring guide.
"""
from __future__ import annotations
import logging
from importlib.metadata import entry_points
ENTRY_POINT_GROUP = "lightrag.parsers"
logger = logging.getLogger("lightrag")
_loaded = False
def load_third_party_parsers(*, force: bool = False) -> list[str]:
"""Discover and run all ``lightrag.parsers`` entry points.
Idempotent per process (``force=True`` re-runs, for tests). Returns the
names of the entry points that loaded successfully. A failing plugin is
logged with its origin and skipped — one broken third-party package must
not take down server startup or the debug CLI; the built-in engines are
registered statically and are never affected.
"""
global _loaded
if _loaded and not force:
return []
_loaded = True
loaded: list[str] = []
for ep in entry_points(group=ENTRY_POINT_GROUP):
try:
register = ep.load()
register()
except Exception as e:
logger.error(
"[parser-plugins] failed to load parser plugin %r (%s): %s",
ep.name,
ep.value,
e,
)
continue
loaded.append(ep.name)
logger.info("[parser-plugins] loaded parser plugin %r (%s)", ep.name, ep.value)
return loaded