Repository: deepset-ai/haystack
Pull request: feat: widen support of env vars in OpenAI components
### Related Issues

- fixes #7610

### Proposed Changes:

Now you can change the timeout and max retries of your OpenAI clients (`OpenAIDocumentEmbedder`, `OpenAITextEmbedder`, `OpenAIGenerator` and `OpenAIChatGenerator`) just by using the `OPENAI_TIMEOUT` and `OPENAI_MAX_RETRIES` environment variables.

### How did you test it?

<!-- unit tests, integration tests, manual verification, instructions for manual tests -->
Enriched the unit tests of all this classes to test how this variables can be set.


### Checklist

- I have read the [contributors guidelines](https://github.com/deepset-ai/haystack/blob/main/CONTRIBUTING.md) and the [code of conduct](https://github.com/deepset-ai/haystack/blob/main/code_of_conduct.txt) ✅
- I have updated the related issue with new insights and changes ✅
- I added unit tests and updated the docstrings ✅
- I've used one of the [conventional commit types](https://www.conventionalcommits.org/en/v1.0.0/) for my PR title: `fix:`, `feat:`, `build:`, `chore:`, `ci:`, `docs:`, `style:`, `refactor:`, `perf:`, `test:`. ✅
- I documented my code ✅
- I ran [pre-commit hooks](https://github.com/deepset-ai/haystack/blob/main/CONTRIBUTING.md#installation) and fixed any issue ✅


Problem statement:
Add enviroment variable for openai timeout, backoff and max retries
**Is your feature request related to a problem? Please describe.**
In version 1, haystack allows to set three environment variables to manage:
* OPENAI_TIMEOUT
* OPENAI_MAX_RETRIES
* OPENAI_BACKOFF

It's useful also for the versione 2.0

Hints from issue discussion:
Working on it.
@nickprock, I've been locking for this environment variables on the v1.x and v1.25.x branches and cannot find any reference to them, could you give me more info please.
In 1.25 there are these environment variables

```
# Any remote API (OpenAI, Cohere etc.)
HAYSTACK_REMOTE_API_BACKOFF_SEC = "HAYSTACK_REMOTE_API_BACKOFF_SEC"
HAYSTACK_REMOTE_API_MAX_RETRIES = "HAYSTACK_REMOTE_API_MAX_RETRIES"
HAYSTACK_REMOTE_API_TIMEOUT_SEC = "HAYSTACK_REMOTE_API_TIMEOUT_SEC"
HAYSTACK_PROMPT_TEMPLATE_ALLOWED_FUNCTIONS = "HAYSTACK_PROMPT_TEMPLATE_ALLOWED_FUNCTIONS"
```
https://github.com/deepset-ai/haystack/blob/v1.25.5/haystack/environment.py

I talked with @vblagoje on Discord here: https://discord.com/channels/993534733298450452/1232706764294717511
@nickprock the discord invitation does not work. Could you send a new one please.
https://discord.com/invite/FKYDefGP
Not really getting anywhere, and I will be out for the next few days, so feel free to proceed with this implementation. :)
Hey @masci just wanted to give you a heads up that deepset Cloud + Sol will want this since we used this extensively for client pipelines that timed out when using bigger models like GPT4.

Commit message: reverse changes to telemetry/_enviroment.py

Patch to review:
diff --git a/haystack/components/embedders/openai_document_embedder.py b/haystack/components/embedders/openai_document_embedder.py
index 4bc189dd4f..b129f68ea9 100644
--- a/haystack/components/embedders/openai_document_embedder.py
+++ b/haystack/components/embedders/openai_document_embedder.py
@@ -2,6 +2,7 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 
+import os
 from typing import Any, Dict, List, Optional, Tuple
 
 from openai import OpenAI
@@ -45,10 +46,15 @@ def __init__(
         progress_bar: bool = True,
         meta_fields_to_embed: Optional[List[str]] = None,
         embedding_separator: str = "\n",
+        timeout: Optional[float] = None,
+        max_retries: Optional[int] = None,
     ):
         """
         Create a OpenAIDocumentEmbedder component.
 
+        By setting the 'OPENAI_TIMEOUT' and 'OPENAI_MAX_RETRIES' you can change the timeout and max_retries parameters in the OpenAI client.
+
+
         :param api_key:
             The OpenAI API key.
         :param model:
@@ -73,6 +79,10 @@ def __init__(
             List of meta fields that will be embedded along with the Document text.
         :param embedding_separator:
             Separator used to concatenate the meta fields to the Document text.
+        :param timeout:
+            Timeout for OpenAI Client calls, if not set it is inferred from the `OPENAI_TIMEOUT` environment variable or set to 30.
+        :param max_retries:
+            Maximum retries to stablish contact with OpenAI if it returns an internal error, if not set it is inferred from the `OPENAI_MAX_RETRIES` environment variable or set to 5.
         """
         self.api_key = api_key
         self.model = model
@@ -86,7 +96,18 @@ def __init__(
         self.meta_fields_to_embed = meta_fields_to_embed or []
         self.embedding_separator = embedding_separator
 
-        self.client = OpenAI(api_key=api_key.resolve_value(), organization=organization, base_url=api_base_url)
+        if timeout is None:
+            timeout = float(os.environ.get("OPENAI_TIMEOUT", 30.0))
+        if max_retries is None:
+            max_retries = int(os.environ.get("OPENAI_MAX_RETRIES", 5))
+
+        self.client = OpenAI(
+            api_key=api_key.resolve_value(),
+            organization=organization,
+            base_url=api_base_url,
+            timeout=timeout,
+            max_retries=max_retries,
+        )
 
     def _get_telemetry_data(self) -> Dict[str, Any]:
         """
diff --git a/haystack/components/embedders/openai_text_embedder.py b/haystack/components/embedders/openai_text_embedder.py
index 347d6a186e..b78d9f0a2f 100644
--- a/haystack/components/embedders/openai_text_embedder.py
+++ b/haystack/components/embedders/openai_text_embedder.py
@@ -2,6 +2,7 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 
+import os
 from typing import Any, Dict, List, Optional
 
 from openai import OpenAI
@@ -9,6 +10,9 @@
 from haystack import component, default_from_dict, default_to_dict
 from haystack.utils import Secret, deserialize_secrets_inplace
 
+OPENAI_TIMEOUT = float(os.environ.get("OPENAI_API_KEY", 30))
+OPENAI_MAX_RETRIES = int(os.environ.get("OPENAI_MAX_RETRIES", 5))
+
 
 @component
 class OpenAITextEmbedder:
@@ -40,10 +44,14 @@ def __init__(
         organization: Optional[str] = None,
         prefix: str = "",
         suffix: str = "",
+        timeout: Optional[float] = None,
+        max_retries: Optional[int] = None,
     ):
         """
         Create an OpenAITextEmbedder component.
 
+        By setting the 'OPENAI_TIMEOUT' and 'OPENAI_MAX_RETRIES' you can change the timeout and max_retries parameters in the OpenAI client.
+
         :param api_key:
             The OpenAI API key.
         :param model:
@@ -60,6 +68,10 @@ def __init__(
             A string to add at the beginning of each text.
         :param suffix:
             A string to add at the end of each text.
+        :param timeout:
+            Timeout for OpenAI Client calls, if not set it is inferred from the `OPENAI_TIMEOUT` environment variable or set to 30.
+        :param max_retries:
+            Maximum retries to stablish contact with OpenAI if it returns an internal error, if not set it is inferred from the `OPENAI_MAX_RETRIES` environment variable or set to 5.
         """
         self.model = model
         self.dimensions = dimensions
@@ -69,7 +81,18 @@ def __init__(
         self.suffix = suffix
         self.api_key = api_key
 
-        self.client = OpenAI(api_key=api_key.resolve_value(), organization=organization, base_url=api_base_url)
+        if timeout is None:
+            timeout = float(os.environ.get("OPENAI_TIMEOUT", 30.0))
+        if max_retries is None:
+            max_retries = int(os.environ.get("OPENAI_MAX_RETRIES", 5))
+
+        self.client = OpenAI(
+            api_key=api_key.resolve_value(),
+            organization=organization,
+            base_url=api_base_url,
+            timeout=timeout,
+            max_retries=max_retries,
+        )
 
     def _get_telemetry_data(self) -> Dict[str, Any]:
         """
diff --git a/haystack/components/generators/chat/openai.py b/haystack/components/generators/chat/openai.py
index 8bef38e370..2bb4a6a985 100644
--- a/haystack/components/generators/chat/openai.py
+++ b/haystack/components/generators/chat/openai.py
@@ -4,6 +4,7 @@
 
 import copy
 import json
+import os
 from typing import Any, Callable, Dict, List, Optional, Union
 
 from openai import OpenAI, Stream
@@ -75,6 +76,8 @@ def __init__(
         api_base_url: Optional[str] = None,
         organization: Optional[str] = None,
         generation_kwargs: Optional[Dict[str, Any]] = None,
+        timeout: Optional[float] = None,
+        max_retries: Optional[int] = None,
     ):
         """
         Initializes the OpenAIChatGenerator component.
@@ -82,6 +85,8 @@ def __init__(
         Creates an instance of OpenAIChatGenerator. Unless specified otherwise in the `model`, this is for OpenAI's
         GPT-3.5 model.
 
+        By setting the 'OPENAI_TIMEOUT' and 'OPENAI_MAX_RETRIES' you can change the timeout and max_retries parameters in the OpenAI client.
+
         :param api_key: The OpenAI API key.
         :param model: The name of the model to use.
         :param streaming_callback: A callback function that is called when a new token is received from the stream.
@@ -108,6 +113,10 @@ def __init__(
                 Bigger values mean the model will be less likely to repeat the same token in the text.
             - `logit_bias`: Add a logit bias to specific tokens. The keys of the dictionary are tokens, and the
                 values are the bias to add to that token.
+        :param timeout:
+            Timeout for OpenAI Client calls, if not set it is inferred from the `OPENAI_TIMEOUT` environment variable or set to 30.
+        :param max_retries:
+            Maximum retries to stablish contact with OpenAI if it returns an internal error, if not set it is inferred from the `OPENAI_MAX_RETRIES` environment variable or set to 5.
         """
         self.api_key = api_key
         self.model = model
@@ -115,7 +124,19 @@ def __init__(
         self.streaming_callback = streaming_callback
         self.api_base_url = api_base_url
         self.organization = organization
-        self.client = OpenAI(api_key=api_key.resolve_value(), organization=organization, base_url=api_base_url)
+
+        if timeout is None:
+            timeout = float(os.environ.get("OPENAI_TIMEOUT", 30.0))
+        if max_retries is None:
+            max_retries = int(os.environ.get("OPENAI_MAX_RETRIES", 5))
+
+        self.client = OpenAI(
+            api_key=api_key.resolve_value(),
+            organization=organization,
+            base_url=api_base_url,
+            timeout=timeout,
+            max_retries=max_retries,
+        )
 
     def _get_telemetry_data(self) -> Dict[str, Any]:
         """
diff --git a/haystack/components/generators/openai.py b/haystack/components/generators/openai.py
index d2a37bb76e..fc2a5aae04 100644
--- a/haystack/components/generators/openai.py
+++ b/haystack/components/generators/openai.py
@@ -2,6 +2,7 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 
+import os
 from typing import Any, Callable, Dict, List, Optional, Union
 
 from openai import OpenAI, Stream
@@ -60,10 +61,15 @@ def __init__(
         organization: Optional[str] = None,
         system_prompt: Optional[str] = None,
         generation_kwargs: Optional[Dict[str, Any]] = None,
+        timeout: Optional[float] = None,
+        max_retries: Optional[int] = None,
     ):
         """
         Creates an instance of OpenAIGenerator. Unless specified otherwise in the `model`, this is for OpenAI's GPT-3.5 model.
 
+        By setting the 'OPENAI_TIMEOUT' and 'OPENAI_MAX_RETRIES' you can change the timeout and max_retries parameters in the OpenAI client.
+
+
         :param api_key: The OpenAI API key.
         :param model: The name of the model to use.
         :param streaming_callback: A callback function that is called when a new token is received from the stream.
@@ -92,6 +98,11 @@ def __init__(
                 Bigger values mean the model will be less likely to repeat the same token in the text.
             - `logit_bias`: Add a logit bias to specific tokens. The keys of the dictionary are tokens, and the
                 values are the bias to add to that token.
+        :param timeout:
+            Timeout for OpenAI Client calls, if not set it is inferred from the `OPENAI_TIMEOUT` environment variable or set to 30.
+        :param max_retries:
+            Maximum retries to stablish contact with OpenAI if it returns an internal error, if not set it is inferred from the `OPENAI_MAX_RETRIES` environment variable or set to 5.
+
         """
         self.api_key = api_key
         self.model = model
@@ -101,7 +112,19 @@ def __init__(
 
         self.api_base_url = api_base_url
         self.organization = organization
-        self.client = OpenAI(api_key=api_key.resolve_value(), organization=organization, base_url=api_base_url)
+
+        if timeout is None:
+            timeout = float(os.environ.get("OPENAI_TIMEOUT", 30.0))
+        if max_retries is None:
+            max_retries = int(os.environ.get("OPENAI_MAX_RETRIES", 5))
+
+        self.client = OpenAI(
+            api_key=api_key.resolve_value(),
+            organization=organization,
+            base_url=api_base_url,
+            timeout=timeout,
+            max_retries=max_retries,
+        )
 
     def _get_telemetry_data(self) -> Dict[str, Any]:
         """
diff --git a/haystack/telemetry/_environment.py b/haystack/telemetry/_environment.py
index 2da0aa357a..f5c92b9e45 100644
--- a/haystack/telemetry/_environment.py
+++ b/haystack/telemetry/_environment.py
@@ -12,7 +12,6 @@
 
 logger = logging.getLogger(__name__)
 
-
 # This value cannot change during the lifetime of the process
 _IS_DOCKER_CACHE = None
 
diff --git a/releasenotes/notes/feat-widen-support-of-envars-vars-on-openai-components-efe6203c0c6bd7b3.yaml b/releasenotes/notes/feat-widen-support-of-envars-vars-on-openai-components-efe6203c0c6bd7b3.yaml
new file mode 100644
index 0000000000..acc1d7fc46
--- /dev/null
+++ b/releasenotes/notes/feat-widen-support-of-envars-vars-on-openai-components-efe6203c0c6bd7b3.yaml
@@ -0,0 +1,9 @@
+---
+highlights: >
+    Add the 'OPENAI_TIMEOUT' and 'OPENAI_MAX_RETRIES' to the OpenAI components.
+enhancements:
+  - |
+    Now you can set the timeout and max_retries parameters on OpenAI components by setting the 'OPENAI_TIMEOUT' and 'OPENAI_MAX_RETRIES' environment vars or passing them at __init__.
+issues:
+  - |
+    7610
diff --git a/test/components/embedders/test_openai_document_embedder.py b/test/components/embedders/test_openai_document_embedder.py
index 0995cb29ce..f64a3aca12 100644
--- a/test/components/embedders/test_openai_document_embedder.py
+++ b/test/components/embedders/test_openai_document_embedder.py
@@ -29,6 +29,7 @@ class TestOpenAIDocumentEmbedder:
     def test_init_default(self, monkeypatch):
         monkeypatch.setenv("OPENAI_API_KEY", "fake-api-key")
         embedder = OpenAIDocumentEmbedder()
+        assert embedder.api_key.resolve_value() == "fake-api-key"
         assert embedder.model == "text-embedding-ada-002"
         assert embedder.organization is None
         assert embedder.prefix == ""
@@ -37,10 +38,14 @@ def test_init_default(self, monkeypatch):
         assert embedder.progress_bar is True
         assert embedder.meta_fields_to_embed == []
         assert embedder.embedding_separator == "\n"
+        assert embedder.client.max_retries == 5
+        assert embedder.client.timeout == 30.0
 
-    def test_init_with_parameters(self):
+    def test_init_with_parameters(self, monkeypatch):
+        monkeypatch.setenv("OPENAI_TIMEOUT", "100")
+        monkeypatch.setenv("OPENAI_MAX_RETRIES", "10")
         embedder = OpenAIDocumentEmbedder(
-            api_key=Secret.from_token("fake-api-key"),
+            api_key=Secret.from_token("fake-api-key-2"),
             model="model",
             organization="my-org",
             prefix="prefix",
@@ -49,7 +54,10 @@ def test_init_with_parameters(self):
             progress_bar=False,
             meta_fields_to_embed=["test_field"],
             embedding_separator=" | ",
+            timeout=40.0,
+            max_retries=1,
         )
+        assert embedder.api_key.resolve_value() == "fake-api-key-2"
         assert embedder.organization == "my-org"
         assert embedder.model == "model"
         assert embedder.prefix == "prefix"
@@ -58,6 +66,34 @@ def test_init_with_parameters(self):
         assert embedder.progress_bar is False
         assert embedder.meta_fields_to_embed == ["test_field"]
         assert embedder.embedding_separator == " | "
+        assert embedder.client.max_retries == 1
+        assert embedder.client.timeout == 40.0
+
+    def test_init_with_parameters_and_env_vars(self, monkeypatch):
+        monkeypatch.setenv("OPENAI_TIMEOUT", "100")
+        monkeypatch.setenv("OPENAI_MAX_RETRIES", "10")
+        embedder = OpenAIDocumentEmbedder(
+            api_key=Secret.from_token("fake-api-key-2"),
+            model="model",
+            organization="my-org",
+            prefix="prefix",
+            suffix="suffix",
+            batch_size=64,
+            progress_bar=False,
+            meta_fields_to_embed=["test_field"],
+            embedding_separator=" | ",
+        )
+        assert embedder.api_key.resolve_value() == "fake-api-key-2"
+        assert embedder.organization == "my-org"
+        assert embedder.model == "model"
+        assert embedder.prefix == "prefix"
+        assert embedder.suffix == "suffix"
+        assert embedder.batch_size == 64
+        assert embedder.progress_bar is False
+        assert embedder.meta_fields_to_embed == ["test_field"]
+        assert embedder.embedding_separator == " | "
+        assert embedder.client.max_retries == 10
+        assert embedder.client.timeout == 100.0
 
     def test_init_fail_wo_api_key(self, monkeypatch):
         monkeypatch.delenv("OPENAI_API_KEY", raising=False)
diff --git a/test/components/embedders/test_openai_text_embedder.py b/test/components/embedders/test_openai_text_embedder.py
index c7848676fe..31a0360555 100644
--- a/test/components/embedders/test_openai_text_embedder.py
+++ b/test/components/embedders/test_openai_text_embedder.py
@@ -20,8 +20,12 @@ def test_init_default(self, monkeypatch):
         assert embedder.organization is None
         assert embedder.prefix == ""
         assert embedder.suffix == ""
+        assert embedder.client.timeout == 30
+        assert embedder.client.max_retries == 5
 
-    def test_init_with_parameters(self):
+    def test_init_with_parameters(self, monkeypatch):
+        monkeypatch.setenv("OPENAI_TIMEOUT", "100")
+        monkeypatch.setenv("OPENAI_MAX_RETRIES", "10")
         embedder = OpenAITextEmbedder(
             api_key=Secret.from_token("fake-api-key"),
             model="model",
@@ -29,6 +33,8 @@ def test_init_with_parameters(self):
             organization="fake-organization",
             prefix="prefix",
             suffix="suffix",
+            timeout=40.0,
+            max_retries=1,
         )
         assert embedder.client.api_key == "fake-api-key"
         assert embedder.model == "model"
@@ -36,6 +42,28 @@ def test_init_with_parameters(self):
         assert embedder.organization == "fake-organization"
         assert embedder.prefix == "prefix"
         assert embedder.suffix == "suffix"
+        assert embedder.client.timeout == 40.0
+        assert embedder.client.max_retries == 1
+
+    def test_init_with_parameters_and_env_vars(self, monkeypatch):
+        monkeypatch.setenv("OPENAI_TIMEOUT", "100")
+        monkeypatch.setenv("OPENAI_MAX_RETRIES", "10")
+        embedder = OpenAITextEmbedder(
+            api_key=Secret.from_token("fake-api-key"),
+            model="model",
+            api_base_url="https://my-custom-base-url.com",
+            organization="fake-organization",
+            prefix="prefix",
+            suffix="suffix",
+        )
+        assert embedder.client.api_key == "fake-api-key"
+        assert embedder.model == "model"
+        assert embedder.api_base_url == "https://my-custom-base-url.com"
+        assert embedder.organization == "fake-organization"
+        assert embedder.prefix == "prefix"
+        assert embedder.suffix == "suffix"
+        assert embedder.client.timeout == 100.0
+        assert embedder.client.max_retries == 10
 
     def test_init_fail_wo_api_key(self, monkeypatch):
         monkeypatch.delenv("OPENAI_API_KEY", raising=False)
diff --git a/test/components/generators/chat/test_openai.py b/test/components/generators/chat/test_openai.py
index 8f40c2fd08..e945121755 100644
--- a/test/components/generators/chat/test_openai.py
+++ b/test/components/generators/chat/test_openai.py
@@ -29,24 +29,49 @@ def test_init_default(self, monkeypatch):
         assert component.model == "gpt-3.5-turbo"
         assert component.streaming_callback is None
         assert not component.generation_kwargs
+        assert component.client.timeout == 30
+        assert component.client.max_retries == 5
 
     def test_init_fail_wo_api_key(self, monkeypatch):
         monkeypatch.delenv("OPENAI_API_KEY", raising=False)
         with pytest.raises(ValueError, match="None of the .* environment variables are set"):
             OpenAIChatGenerator()
 
-    def test_init_with_parameters(self):
+    def test_init_with_parameters(self, monkeypatch):
+        monkeypatch.setenv("OPENAI_TIMEOUT", "100")
+        monkeypatch.setenv("OPENAI_MAX_RETRIES", "10")
         component = OpenAIChatGenerator(
             api_key=Secret.from_token("test-api-key"),
             model="gpt-4",
             streaming_callback=print_streaming_chunk,
             api_base_url="test-base-url",
             generation_kwargs={"max_tokens": 10, "some_test_param": "test-params"},
+            timeout=40.0,
+            max_retries=1,
         )
         assert component.client.api_key == "test-api-key"
         assert component.model == "gpt-4"
         assert component.streaming_callback is print_streaming_chunk
         assert component.generation_kwargs == {"max_tokens": 10, "some_test_param": "test-params"}
+        assert component.client.timeout == 40.0
+        assert component.client.max_retries == 1
+
+    def test_init_with_parameters_and_env_vars(self, monkeypatch):
+        monkeypatch.setenv("OPENAI_TIMEOUT", "100")
+        monkeypatch.setenv("OPENAI_MAX_RETRIES", "10")
+        component = OpenAIChatGenerator(
+            api_key=Secret.from_token("test-api-key"),
+            model="gpt-4",
+            streaming_callback=print_streaming_chunk,
+            api_base_url="test-base-url",
+            generation_kwargs={"max_tokens": 10, "some_test_param": "test-params"},
+        )
+        assert component.client.api_key == "test-api-key"
+        assert component.model == "gpt-4"
+        assert component.streaming_callback is print_streaming_chunk
+        assert component.generation_kwargs == {"max_tokens": 10, "some_test_param": "test-params"}
+        assert component.client.timeout == 100.0
+        assert component.client.max_retries == 10
 
     def test_to_dict_default(self, monkeypatch):
         monkeypatch.setenv("OPENAI_API_KEY", "test-api-key")
diff --git a/test/components/generators/test_openai.py b/test/components/generators/test_openai.py
index 714c807668..6fe807210d 100644
--- a/test/components/generators/test_openai.py
+++ b/test/components/generators/test_openai.py
@@ -22,24 +22,49 @@ def test_init_default(self, monkeypatch):
         assert component.model == "gpt-3.5-turbo"
         assert component.streaming_callback is None
         assert not component.generation_kwargs
+        assert component.client.timeout == 30
+        assert component.client.max_retries == 5
 
     def test_init_fail_wo_api_key(self, monkeypatch):
         monkeypatch.delenv("OPENAI_API_KEY", raising=False)
         with pytest.raises(ValueError, match="None of the .* environment variables are set"):
             OpenAIGenerator()
 
-    def test_init_with_parameters(self):
+    def test_init_with_parameters(self, monkeypatch):
+        monkeypatch.setenv("OPENAI_TIMEOUT", "100")
+        monkeypatch.setenv("OPENAI_MAX_RETRIES", "10")
         component = OpenAIGenerator(
             api_key=Secret.from_token("test-api-key"),
             model="gpt-4",
             streaming_callback=print_streaming_chunk,
             api_base_url="test-base-url",
             generation_kwargs={"max_tokens": 10, "some_test_param": "test-params"},
+            timeout=40.0,
+            max_retries=1,
         )
         assert component.client.api_key == "test-api-key"
         assert component.model == "gpt-4"
         assert component.streaming_callback is print_streaming_chunk
         assert component.generation_kwargs == {"max_tokens": 10, "some_test_param": "test-params"}
+        assert component.client.timeout == 40.0
+        assert component.client.max_retries == 1
+
+    def test_init_with_parameters(self, monkeypatch):
+        monkeypatch.setenv("OPENAI_TIMEOUT", "100")
+        monkeypatch.setenv("OPENAI_MAX_RETRIES", "10")
+        component = OpenAIGenerator(
+            api_key=Secret.from_token("test-api-key"),
+            model="gpt-4",
+            streaming_callback=print_streaming_chunk,
+            api_base_url="test-base-url",
+            generation_kwargs={"max_tokens": 10, "some_test_param": "test-params"},
+        )
+        assert component.client.api_key == "test-api-key"
+        assert component.model == "gpt-4"
+        assert component.streaming_callback is print_streaming_chunk
+        assert component.generation_kwargs == {"max_tokens": 10, "some_test_param": "test-params"}
+        assert component.client.timeout == 100.0
+        assert component.client.max_retries == 10
 
     def test_to_dict_default(self, monkeypatch):
         monkeypatch.setenv("OPENAI_API_KEY", "test-api-key")


Code review comments:
diff_hunk: @@ -2,13 +2,17 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 
+import os
 from typing import Any, Dict, List, Optional
 
 from openai import OpenAI
 
 from haystack import component, default_from_dict, default_to_dict
 from haystack.utils import Secret, deserialize_secrets_inplace
 
+OPENAI_TIMEOUT = float(os.environ.get("OPENAI_API_KEY", 30))
path: haystack/components/embedders/openai_text_embedder.py
text: @user1:
```suggestion
OPENAI_TIMEOUT = float(os.environ.get("OPENAI_TIMEOUT", 30))
```