| 1 | # SPDX-License-Identifier: Apache-2.0 |
| 2 | # SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
| 3 | from dataclasses import dataclass, field |
| 4 | from typing import TYPE_CHECKING |
| 5 | |
| 6 | from vllm.logger import init_logger |
| 7 | from vllm.tokenizers import TokenizerLike |
| 8 | from vllm.tokenizers.registry import ( |
| 9 | cached_tokenizer_from_config, |
| 10 | tokenizer_args_from_config, |
| 11 | ) |
| 12 | from vllm.utils.import_utils import resolve_obj_by_qualname |
| 13 | |
| 14 | from .base import BaseRenderer |
| 15 | |
| 16 | if TYPE_CHECKING: |
| 17 | from vllm.config import VllmConfig |
| 18 | |
| 19 | logger = init_logger(__name__) |
| 20 | |
| 21 | |
| 22 | _VLLM_RENDERERS = { |
| 23 | "cohere": ("cohere", "CohereRenderer"), |
| 24 | "deepseek_v32": ("deepseek_v32", "DeepseekV32Renderer"), |
| 25 | "deepseek_v4": ("deepseek_v4", "DeepseekV4Renderer"), |
| 26 | "deepseek_v41": ("deepseek_v4", "DeepseekV4Renderer"), |
| 27 | "hf": ("hf", "HfRenderer"), |
| 28 | "kimi_audio": ("hf", "HfRenderer"), |
| 29 | "kimi_k3": ("kimi_k3", "KimiK3Renderer"), |
| 30 | "mistral": ("mistral", "MistralRenderer"), |
| 31 | "terratorch": ("terratorch", "TerratorchRenderer"), |
| 32 | "inkling": ("inkling", "InklingRenderer"), |
| 33 | } |
| 34 | |
| 35 | |
| 36 | @dataclass |
| 37 | class RendererRegistry: |
| 38 | # Renderer mode -> (renderer module, renderer class) |
| 39 | renderers: dict[str, tuple[str, str]] = field(default_factory=dict) |
| 40 | |
| 41 | def register(self, renderer_mode: str, module: str, class_name: str) -> None: |
| 42 | if renderer_mode in self.renderers: |
| 43 | logger.warning( |
| 44 | "%s.%s is already registered for renderer_mode=%r. " |
| 45 | "It is overwritten by the new one.", |
| 46 | module, |
| 47 | class_name, |
| 48 | renderer_mode, |
| 49 | ) |
| 50 | |
| 51 | self.renderers[renderer_mode] = (module, class_name) |
| 52 | |
| 53 | return None |
| 54 | |
| 55 | def load_renderer_cls(self, renderer_mode: str) -> type[BaseRenderer]: |
| 56 | if renderer_mode not in self.renderers: |
| 57 | raise ValueError(f"No renderer registered for {renderer_mode=!r}.") |
| 58 | |
| 59 | module, class_name = self.renderers[renderer_mode] |
| 60 | logger.debug_once(f"Loading {class_name} for {renderer_mode=!r}") |
| 61 | |
| 62 | return resolve_obj_by_qualname(f"{module}.{class_name}") |
| 63 | |
| 64 | def load_renderer( |
| 65 | self, |
| 66 | renderer_mode: str, |
| 67 | config: "VllmConfig", |
| 68 | tokenizer: TokenizerLike | None, |
| 69 | ) -> BaseRenderer: |
| 70 | renderer_cls = self.load_renderer_cls(renderer_mode) |
| 71 | return renderer_cls(config, tokenizer) |
| 72 | |
| 73 | |
| 74 | RENDERER_REGISTRY = RendererRegistry( |
| 75 | { |
| 76 | mode: (f"vllm.renderers.{mod_relname}", cls_name) |
| 77 | for mode, (mod_relname, cls_name) in _VLLM_RENDERERS.items() |
| 78 | } |
| 79 | ) |
| 80 | """The global `RendererRegistry` instance.""" |
| 81 | |
| 82 | |
| 83 | def renderer_from_config(config: "VllmConfig", **kwargs): |
| 84 | model_config = config.model_config |
| 85 | |
| 86 | tokenizer = cached_tokenizer_from_config(model_config, **kwargs) |
| 87 | renderer_mode, *_ = tokenizer_args_from_config(model_config, **kwargs) |
| 88 | |
| 89 | return RENDERER_REGISTRY.load_renderer(renderer_mode, config, tokenizer) |