Repository: huggingface/transformers
Pull request: Fix CLI NameError: name 'TypeAdapter' is not defined

Fix CLI NameError: name 'TypeAdapter' is not defined:
- Do not evaluate type annotations in CLI serve

### Problem

Calling the CLI raises NameError:
> NameError: name 'TypeAdapter' is not defined
```bash
transformers --help
```
```python
Traceback (most recent call last):
  File "huggingface/transformers/.venv/bin/transformers", line 4, in <module>
    from transformers.cli.transformers import main
  File "huggingface/transformers/src/transformers/cli/transformers.py", line 22, in <module>
    from transformers.cli.serve import Serve
  File "huggingface/transformers/src/transformers/cli/serve.py", line 360, in <module>
    class Serve:
  File "huggingface/transformers/src/transformers/cli/serve.py", line 588, in Serve
    validator: TypeAdapter,
               ^^^^^^^^^^^
NameError: name 'TypeAdapter' is not defined
```

### Solution

This PR adds a future import for annotations in CLI, to fix compatibility and type hinting in the code.

### Who can review?

CC: @remi-or @LysandreJik, who previously contributed to the CLI serve.



Changed files:
filename: src/transformers/cli/serve.py
patch: @@ -11,6 +11,9 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
+from __future__ import annotations
+
 import asyncio
 import base64
 import copy
@@ -28,7 +31,7 @@
 from functools import lru_cache
 from io import BytesIO
 from threading import Thread
-from typing import TYPE_CHECKING, Annotated, Optional, TypedDict, Union
+from typing import TYPE_CHECKING, Annotated, TypedDict
 
 import typer
 from huggingface_hub import scan_cache_dir
@@ -313,9 +316,9 @@ class TimedModel:
 
     def __init__(
         self,
-        model: "PreTrainedModel",
+        model: PreTrainedModel,
         timeout_seconds: int,
-        processor: Union["ProcessorMixin", "PreTrainedTokenizerFast"] | None = None,
+        processor: ProcessorMixin | PreTrainedTokenizerFast | None = None,
     ):
         self.model = model
         self._name_or_path = str(model.name_or_path)
@@ -663,7 +666,7 @@ def build_chat_completion_chunk(
         finish_reason: str | None = None,
         tool_calls: list[ChoiceDeltaToolCall] | None = None,
         decode_stream: DecodeStream | None = None,
-        tokenizer: Optional["PreTrainedTokenizerFast"] = None,
+        tokenizer: PreTrainedTokenizerFast | None = None,
     ) -> ChatCompletionChunk:
         """
         Builds a chunk of a streaming OpenAI Chat Completion response.
@@ -935,7 +938,7 @@ def cancellation_wrapper_buffer(_request_id):
             return JSONResponse(json_chunk, media_type="application/json")
 
     @staticmethod
-    def get_model_modality(model: "PreTrainedModel", processor=None) -> Modality:
+    def get_model_modality(model: PreTrainedModel, processor=None) -> Modality:
         if processor is not None:
             if isinstance(processor, PreTrainedTokenizerBase):
                 return Modality.LLM
@@ -1850,9 +1853,7 @@ def _load_model_and_data_processor(self, model_id_and_revision: str):
         logger.info(f"Loaded model {model_id_and_revision}")
         return model, data_processor
 
-    def load_model_and_processor(
-        self, model_id_and_revision: str
-    ) -> tuple["PreTrainedModel", "PreTrainedTokenizerFast"]:
+    def load_model_and_processor(self, model_id_and_revision: str) -> tuple[PreTrainedModel, PreTrainedTokenizerFast]:
         """
         Loads the text model and processor from the given model ID and revision into the ServeCommand instance.
 
@@ -1877,7 +1878,7 @@ def load_model_and_processor(
 
         return model, processor
 
-    def load_audio_model_and_processor(self, model_id_and_revision: str) -> tuple["PreTrainedModel", "ProcessorMixin"]:
+    def load_audio_model_and_processor(self, model_id_and_revision: str) -> tuple[PreTrainedModel, ProcessorMixin]:
         """
         Loads the audio model and processor from the given model ID and revision into the ServeCommand instance.