| 1 | # SPDX-License-Identifier: Apache-2.0 |
| 2 | # SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
| 3 | """``fastokens`` backend patch. |
| 4 | |
| 5 | When ``VLLM_USE_FASTOKENS=1`` is set, ``fastokens.patch_transformers()`` swaps |
| 6 | the inner Rust tokenizer of every HF fast tokenizer loaded afterwards with the |
| 7 | fastokens shim and rebinds ``tokenizers.decoders.DecodeStream`` so the |
| 8 | streaming detokenizer accepts the shim. The patch is process-global and |
| 9 | idempotent, so it applies to any tokenizer mode that ends up loading an HF |
| 10 | fast tokenizer (`hf`, `deepseek_v32`, `deepseek_v4`, …). |
| 11 | """ |
| 12 | |
| 13 | from importlib.metadata import PackageNotFoundError, version |
| 14 | |
| 15 | from packaging.version import Version |
| 16 | |
| 17 | _MIN_FASTOKENS_VERSION = "0.2.0" |
| 18 | |
| 19 | |
| 20 | def apply_fastokens_patch() -> None: |
| 21 | try: |
| 22 | import fastokens |
| 23 | except ImportError as e: |
| 24 | raise ImportError( |
| 25 | f"The 'fastokens' package (>= {_MIN_FASTOKENS_VERSION}) is required " |
| 26 | "when VLLM_USE_FASTOKENS=1." |
| 27 | ) from e |
| 28 | |
| 29 | try: |
| 30 | installed = version("fastokens") |
| 31 | except PackageNotFoundError: |
| 32 | installed = None |
| 33 | if installed is None or Version(installed) < Version(_MIN_FASTOKENS_VERSION): |
| 34 | raise ImportError( |
| 35 | f"fastokens >= {_MIN_FASTOKENS_VERSION} is required when " |
| 36 | f"VLLM_USE_FASTOKENS=1 (found {installed or 'unknown'})." |
| 37 | ) |
| 38 | |
| 39 | fastokens.patch_transformers() |