Repository: deepset-ai/haystack

Issue:
Transformers imports in TGI Generators are not lazily imported
**To Reproduce**
```python
! pip install haystack-ai
from haystack.preview.components.generators import GPTGenerator
```

**Error message**

> ---------------------------------------------------------------------------
> ModuleNotFoundError                       Traceback (most recent call last)
> [<ipython-input-4-181bb29b2164>](https://localhost:8080/#) in <cell line: 1>()
> ----> 1 from haystack.preview.components.generators import GPTGenerator
> 
> 1 frames
> [/usr/local/lib/python3.10/dist-packages/haystack/preview/components/generators/__init__.py](https://localhost:8080/#) in <module>
>       1 from haystack.preview.components.generators.hugging_face.hugging_face_local import HuggingFaceLocalGenerator
> ----> 2 from haystack.preview.components.generators.hugging_face_tgi import HuggingFaceTGIGenerator
>       3 from haystack.preview.components.generators.openai import GPTGenerator
>       4 
>       5 __all__ = ["HuggingFaceLocalGenerator", "HuggingFaceTGIGenerator", "GPTGenerator"]
> 
> [/usr/local/lib/python3.10/dist-packages/haystack/preview/components/generators/hugging_face_tgi.py](https://localhost:8080/#) in <module>
>       4 from urllib.parse import urlparse
>       5 
> ----> 6 from huggingface_hub import InferenceClient
>       7 from huggingface_hub.inference._text_generation import TextGenerationStreamResponse, TextGenerationResponse, Token
>       8 from transformers import AutoTokenizer
> 
> ModuleNotFoundError: No module named 'huggingface_hub'

**Describe the bug**
We should add a lazy import for these `transformers` imports

**System:**
 - Haystack version (commit or version number): preview package -> haystack-ai==0.118.0



Discussion:

Resolving patch:
diff --git a/haystack/preview/components/generators/chat/hugging_face_tgi.py b/haystack/preview/components/generators/chat/hugging_face_tgi.py
--- a/haystack/preview/components/generators/chat/hugging_face_tgi.py
+++ b/haystack/preview/components/generators/chat/hugging_face_tgi.py
@@ -3,14 +3,16 @@
 from typing import Any, Dict, List, Optional, Iterable, Callable
 from urllib.parse import urlparse
 
-from huggingface_hub import InferenceClient
-from huggingface_hub.inference._text_generation import TextGenerationStreamResponse, TextGenerationResponse, Token
-from transformers import AutoTokenizer
-
 from haystack.preview import component, default_to_dict, default_from_dict
-from haystack.preview.components.generators.hf_utils import check_valid_model, check_generation_params
 from haystack.preview.components.generators.utils import serialize_callback_handler, deserialize_callback_handler
 from haystack.preview.dataclasses import ChatMessage, StreamingChunk
+from haystack.preview.components.generators.hf_utils import check_valid_model, check_generation_params
+from haystack.lazy_imports import LazyImport
+
+with LazyImport(message="Run 'pip install transformers'") as transformers_import:
+    from huggingface_hub import InferenceClient
+    from huggingface_hub.inference._text_generation import TextGenerationStreamResponse, TextGenerationResponse, Token
+    from transformers import AutoTokenizer
 
 logger = logging.getLogger(__name__)
 
@@ -108,6 +110,8 @@ def __init__(
         :param stop_words: An optional list of strings representing the stop words.
         :param streaming_callback: An optional callable for handling streaming responses.
         """
+        transformers_import.check()
+
         if url:
             r = urlparse(url)
             is_valid_url = all([r.scheme in ["http", "https"], r.netloc])
diff --git a/haystack/preview/components/generators/hf_utils.py b/haystack/preview/components/generators/hf_utils.py
--- a/haystack/preview/components/generators/hf_utils.py
+++ b/haystack/preview/components/generators/hf_utils.py
@@ -1,8 +1,11 @@
 import inspect
 from typing import Any, Dict, List, Optional
 
-from huggingface_hub import InferenceClient, HfApi
-from huggingface_hub.utils import RepositoryNotFoundError
+from haystack.lazy_imports import LazyImport
+
+with LazyImport(message="Run 'pip install transformers'") as transformers_import:
+    from huggingface_hub import InferenceClient, HfApi
+    from huggingface_hub.utils import RepositoryNotFoundError
 
 
 def check_generation_params(kwargs: Optional[Dict[str, Any]], additional_accepted_params: Optional[List[str]] = None):
@@ -13,6 +16,8 @@ def check_generation_params(kwargs: Optional[Dict[str, Any]], additional_accepte
     :param additional_accepted_params: An optional list of strings representing additional accepted parameters.
     :raises ValueError: If any unknown text generation parameters are provided.
     """
+    transformers_import.check()
+
     if kwargs:
         accepted_params = {
             param
@@ -37,6 +42,8 @@ def check_valid_model(model_id: str, token: Optional[str]) -> None:
     :param token: An optional string representing the authentication token.
     :raises ValueError: If the model is not found or is not a text generation model.
     """
+    transformers_import.check()
+
     api = HfApi()
     try:
         model_info = api.model_info(model_id, token=token)
diff --git a/haystack/preview/components/generators/hugging_face_tgi.py b/haystack/preview/components/generators/hugging_face_tgi.py
--- a/haystack/preview/components/generators/hugging_face_tgi.py
+++ b/haystack/preview/components/generators/hugging_face_tgi.py
@@ -3,14 +3,17 @@
 from typing import Any, Dict, List, Optional, Iterable, Callable
 from urllib.parse import urlparse
 
-from huggingface_hub import InferenceClient
-from huggingface_hub.inference._text_generation import TextGenerationStreamResponse, TextGenerationResponse, Token
-from transformers import AutoTokenizer
-
 from haystack.preview import component, default_to_dict, default_from_dict
-from haystack.preview.components.generators.hf_utils import check_generation_params, check_valid_model
 from haystack.preview.components.generators.utils import serialize_callback_handler, deserialize_callback_handler
 from haystack.preview.dataclasses import StreamingChunk
+from haystack.lazy_imports import LazyImport
+from haystack.preview.components.generators.hf_utils import check_generation_params, check_valid_model
+
+with LazyImport(message="Run 'pip install transformers'") as transformers_import:
+    from huggingface_hub import InferenceClient
+    from huggingface_hub.inference._text_generation import TextGenerationStreamResponse, TextGenerationResponse, Token
+    from transformers import AutoTokenizer
+
 
 logger = logging.getLogger(__name__)
 
@@ -90,6 +93,8 @@ def __init__(
         :param stop_words: An optional list of strings representing the stop words.
         :param streaming_callback: An optional callable for handling streaming responses.
         """
+        transformers_import.check()
+
         if url:
             r = urlparse(url)
             is_valid_url = all([r.scheme in ["http", "https"], r.netloc])


Test patch: