Files
wehub-resource-sync 7ce4c8e27e
pre-commit / pre-run-check (push) Has been cancelled
pre-commit / pre-commit (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:55:37 +08:00

88 lines
3.8 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
"""Contract for `vllm.endpoint_plugins` entry points.
An endpoint plugin adds HTTP routes to the OpenAI compatible API server.
Its scope is HTTP surface only. It registers routes and optionally
per app state used by those routes. It must not open new paths into the
engine by reaching the engine the same way an in-tree serving handler does
via `EngineClient` (e.g. `engine_client.collective_rpc(...)`).
If a plugin also needs engine side behavior (a new worker side RPC method,
a custom stat, etc.) pair this entry point with one registered under
`vllm.general_plugins` (see `vllm/plugins/__init__.py`). The
`general_plugins` entry installs the engine side method and the
`endpoint_plugins` entry exposes it over HTTP. The two are registered and
loaded independently where neither implies the other.
Plugins are opt-in. See `load_endpoint_plugins` in `vllm/plugins/__init__.py`
for the loading/gating rules and `docs/usage/security.md` for the security
posture of exposing plugin defined routes.
The CPU only render server (see `build_and_serve_renderer` in
`vllm/entrypoints/openai/api_server.py`) has no `EngineClient`. A plugin
eligible for the `render` task (`required_tasks` is `None` or includes
`"render"`) still gets `attach_router` called but `init_state` receives
`engine_client=None`. Plugins that cannot function without an engine should
either exclude `"render"` from `required_tasks` or check for `None` in
`init_state`/their route handlers and degrade gracefully.
"""
from argparse import Namespace
from typing import TYPE_CHECKING, Protocol, runtime_checkable
from fastapi import FastAPI
from starlette.datastructures import State
if TYPE_CHECKING:
from vllm.engine.protocol import EngineClient
from vllm.tasks import SupportedTask
@runtime_checkable
class EndpointPlugin(Protocol):
"""Protocol implemented by `vllm.endpoint_plugins` entry point factories.
An entry point registered under the `vllm.endpoint_plugins` group must
resolve to a zero argument callable (a class or factory function) that
returns an object satisfying this protocol.
"""
name: str
"""Unique plugin name used in logs and for `VLLM_PLUGINS` allowlisting."""
required_tasks: "tuple[SupportedTask, ...] | None"
"""Tasks the server must support for this plugin to be loaded.
The plugin is loaded only if this set intersects the server's
`supported_tasks`. `None` means the plugin has no task requirement and
is always eligible (subject to the `VLLM_PLUGINS` allowlist).
"""
def attach_router(self, app: FastAPI) -> None:
"""Register this plugin's routes on `app`.
Called once during `build_app()` after all core routers have been
attached. Routes attached here can shadow core routes with the same
path. There is currently no conflict enforcement (see RFC #46565 follow ups).
"""
...
async def init_state(
self, engine_client: "EngineClient | None", state: State, args: Namespace
) -> None:
"""Initialize per app state consumed by this plugin's routes.
Called once during `init_app_state()` after core state has been
initialized. Use `engine_client` (e.g. `collective_rpc`) to reach
the engine. Do not open new engine access paths.
`engine_client` is `None` on the CPU only render server which has
no engine. This only happens for plugins eligible for the `render`
task (`required_tasks` is `None` or includes `"render"`). Handle
`None` explicitly (e.g. skip engine dependent setup, or have route
handlers return an error) if the plugin is loadable for `render` but
cannot function without an engine.
"""
...