We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add `max_retries` and `timeout` params to all `AzureOpenAI` classes
**Is your feature request related to a problem? Please describe.**

Currently all `OpenAI` related classes (e.g. `OpenAIDocumentEmbedder`, `OpenAIChatGenerator`) can be initialised by setting `max_retries` and `timeout` params.

The corresponding `AzureOpenAI` don't always have the same params.

**Describe the solution you'd like**

It would be nice to have these params in the `AzureOpenAI` classes

**Describe alternatives you've considered**

Subclass `AzureOpenAI` and create custom components.

**Additional context**

cc @anakin87 :)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `haystack/components/generators/chat/azure.py`
Content:
```
1 # SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
2 #
3 # SPDX-License-Identifier: Apache-2.0
4 
5 import os
6 from typing import Any, Callable, Dict, Optional
7 
8 # pylint: disable=import-error
9 from openai.lib.azure import AzureOpenAI
10 
11 from haystack import component, default_from_dict, default_to_dict, logging
12 from haystack.components.generators.chat import OpenAIChatGenerator
13 from haystack.dataclasses import StreamingChunk
14 from haystack.utils import Secret, deserialize_callable, deserialize_secrets_inplace, serialize_callable
15 
16 logger = logging.getLogger(__name__)
17 
18 
19 @component
20 class AzureOpenAIChatGenerator(OpenAIChatGenerator):
21     """
22     A Chat Generator component that uses the Azure OpenAI API to generate text.
23 
24     Enables text generation using OpenAI's large language models (LLMs) on Azure. It supports `gpt-4` and
25     `gpt-3.5-turbo` family of models accessed through the chat completions API endpoint.
26 
27     Users can pass any text generation parameters valid for the `openai.ChatCompletion.create` method
28     directly to this component via the `generation_kwargs` parameter in `__init__` or the `generation_kwargs`
29     parameter in `run` method.
30 
31     For more details on OpenAI models deployed on Azure, refer to the Microsoft
32     [documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/).
33 
34     Key Features and Compatibility:
35      - Primary Compatibility: Designed to work seamlessly with the OpenAI API Chat Completion endpoint.
36      - Streaming Support: Supports streaming responses from the OpenAI API Chat Completion endpoint.
37      - Customizability: Supports all parameters supported by the OpenAI API Chat Completion endpoint.
38 
39     Input and Output Format:
40       - ChatMessage Format: This component uses the ChatMessage format for structuring both input and output, ensuring
41         coherent and contextually relevant responses in chat-based text generation scenarios.
42      - Details on the ChatMessage format can be found [here](https://docs.haystack.deepset.ai/v2.0/docs/data-classes#chatmessage).
43 
44 
45     Usage example:
46 
47     ```python
48     from haystack.components.generators.chat import AzureOpenAIGenerator
49     from haystack.dataclasses import ChatMessage
50     from haystack.utils import Secret
51 
52     messages = [ChatMessage.from_user("What's Natural Language Processing?")]
53 
54     client = AzureOpenAIGenerator(
55         azure_endpoint="<Your Azure endpoint e.g. `https://your-company.azure.openai.com/>",
56         api_key=Secret.from_token("<your-api-key>"),
57         azure_deployment="<this a model name, e.g. gpt-35-turbo>")
58     response = client.run(messages)
59     print(response)
60     ```
61 
62     ```
63     {'replies':
64         [ChatMessage(content='Natural Language Processing (NLP) is a branch of artificial intelligence that focuses on
65          enabling computers to understand, interpret, and generate human language in a way that is useful.',
66          role=<ChatRole.ASSISTANT: 'assistant'>, name=None,
67          meta={'model': 'gpt-3.5-turbo-0613', 'index': 0, 'finish_reason': 'stop',
68          'usage': {'prompt_tokens': 15, 'completion_tokens': 36, 'total_tokens': 51}})]
69     }
70     ```
71     """
72 
73     # pylint: disable=super-init-not-called
74     def __init__(
75         self,
76         azure_endpoint: Optional[str] = None,
77         api_version: Optional[str] = "2023-05-15",
78         azure_deployment: Optional[str] = "gpt-35-turbo",
79         api_key: Optional[Secret] = Secret.from_env_var("AZURE_OPENAI_API_KEY", strict=False),
80         azure_ad_token: Optional[Secret] = Secret.from_env_var("AZURE_OPENAI_AD_TOKEN", strict=False),
81         organization: Optional[str] = None,
82         streaming_callback: Optional[Callable[[StreamingChunk], None]] = None,
83         timeout: Optional[float] = None,
84         generation_kwargs: Optional[Dict[str, Any]] = None,
85     ):
86         """
87         Initialize the Azure OpenAI Chat Generator component.
88 
89         :param azure_endpoint: The endpoint of the deployed model, e.g. `"https://example-resource.azure.openai.com/"`
90         :param api_version: The version of the API to use. Defaults to 2023-05-15
91         :param azure_deployment: The deployment of the model, usually the model name.
92         :param api_key: The API key to use for authentication.
93         :param azure_ad_token: [Azure Active Directory token](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id)
94         :param organization: The Organization ID, defaults to `None`. See
95         [production best practices](https://platform.openai.com/docs/guides/production-best-practices/setting-up-your-organization).
96         :param streaming_callback: A callback function that is called when a new token is received from the stream.
97             The callback function accepts StreamingChunk as an argument.
98         :param generation_kwargs: Other parameters to use for the model. These parameters are all sent directly to
99             the OpenAI endpoint. See OpenAI [documentation](https://platform.openai.com/docs/api-reference/chat) for
100             more details.
101             Some of the supported parameters:
102             - `max_tokens`: The maximum number of tokens the output text can have.
103             - `temperature`: What sampling temperature to use. Higher values mean the model will take more risks.
104                 Try 0.9 for more creative applications and 0 (argmax sampling) for ones with a well-defined answer.
105             - `top_p`: An alternative to sampling with temperature, called nucleus sampling, where the model
106                 considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens
107                 comprising the top 10% probability mass are considered.
108             - `n`: How many completions to generate for each prompt. For example, if the LLM gets 3 prompts and n is 2,
109                 it will generate two completions for each of the three prompts, ending up with 6 completions in total.
110             - `stop`: One or more sequences after which the LLM should stop generating tokens.
111             - `presence_penalty`: What penalty to apply if a token is already present at all. Bigger values mean
112                 the model will be less likely to repeat the same token in the text.
113             - `frequency_penalty`: What penalty to apply if a token has already been generated in the text.
114                 Bigger values mean the model will be less likely to repeat the same token in the text.
115             - `logit_bias`: Add a logit bias to specific tokens. The keys of the dictionary are tokens, and the
116                 values are the bias to add to that token.
117         """
118         # We intentionally do not call super().__init__ here because we only need to instantiate the client to interact
119         # with the API.
120 
121         # Why is this here?
122         # AzureOpenAI init is forcing us to use an init method that takes either base_url or azure_endpoint as not
123         # None init parameters. This way we accommodate the use case where env var AZURE_OPENAI_ENDPOINT is set instead
124         # of passing it as a parameter.
125         azure_endpoint = azure_endpoint or os.environ.get("AZURE_OPENAI_ENDPOINT")
126         if not azure_endpoint:
127             raise ValueError("Please provide an Azure endpoint or set the environment variable AZURE_OPENAI_ENDPOINT.")
128 
129         if api_key is None and azure_ad_token is None:
130             raise ValueError("Please provide an API key or an Azure Active Directory token.")
131 
132         # The check above makes mypy incorrectly infer that api_key is never None,
133         # which propagates the incorrect type.
134         self.api_key = api_key  # type: ignore
135         self.azure_ad_token = azure_ad_token
136         self.generation_kwargs = generation_kwargs or {}
137         self.streaming_callback = streaming_callback
138         self.api_version = api_version
139         self.azure_endpoint = azure_endpoint
140         self.azure_deployment = azure_deployment
141         self.organization = organization
142         self.model = azure_deployment or "gpt-35-turbo"
143         self.timeout = timeout
144 
145         self.client = AzureOpenAI(
146             api_version=api_version,
147             azure_endpoint=azure_endpoint,
148             azure_deployment=azure_deployment,
149             api_key=api_key.resolve_value() if api_key is not None else None,
150             azure_ad_token=azure_ad_token.resolve_value() if azure_ad_token is not None else None,
151             organization=organization,
152         )
153 
154     def to_dict(self) -> Dict[str, Any]:
155         """
156         Serialize this component to a dictionary.
157 
158         :returns:
159             The serialized component as a dictionary.
160         """
161         callback_name = serialize_callable(self.streaming_callback) if self.streaming_callback else None
162         return default_to_dict(
163             self,
164             azure_endpoint=self.azure_endpoint,
165             azure_deployment=self.azure_deployment,
166             organization=self.organization,
167             api_version=self.api_version,
168             streaming_callback=callback_name,
169             generation_kwargs=self.generation_kwargs,
170             timeout=self.timeout,
171             api_key=self.api_key.to_dict() if self.api_key is not None else None,
172             azure_ad_token=self.azure_ad_token.to_dict() if self.azure_ad_token is not None else None,
173         )
174 
175     @classmethod
176     def from_dict(cls, data: Dict[str, Any]) -> "AzureOpenAIChatGenerator":
177         """
178         Deserialize this component from a dictionary.
179 
180         :param data: The dictionary representation of this component.
181         :returns:
182             The deserialized component instance.
183         """
184         deserialize_secrets_inplace(data["init_parameters"], keys=["api_key", "azure_ad_token"])
185         init_params = data.get("init_parameters", {})
186         serialized_callback_handler = init_params.get("streaming_callback")
187         if serialized_callback_handler:
188             data["init_parameters"]["streaming_callback"] = deserialize_callable(serialized_callback_handler)
189         return default_from_dict(cls, data)
190
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/haystack/components/generators/chat/azure.py b/haystack/components/generators/chat/azure.py
--- a/haystack/components/generators/chat/azure.py
+++ b/haystack/components/generators/chat/azure.py
@@ -81,6 +81,7 @@
         organization: Optional[str] = None,
         streaming_callback: Optional[Callable[[StreamingChunk], None]] = None,
         timeout: Optional[float] = None,
+        max_retries: Optional[int] = None,
         generation_kwargs: Optional[Dict[str, Any]] = None,
     ):
         """
@@ -95,6 +96,10 @@
         [production best practices](https://platform.openai.com/docs/guides/production-best-practices/setting-up-your-organization).
         :param streaming_callback: A callback function that is called when a new token is received from the stream.
             The callback function accepts StreamingChunk as an argument.
+        :param timeout: The timeout in seconds to be passed to the underlying `AzureOpenAI` client, if not set it is
+            inferred from the `OPENAI_TIMEOUT` environment variable or set to 30.
+        :param max_retries: Maximum retries to establish a connection with AzureOpenAI if it returns an internal error,
+            if not set it is inferred from the `OPENAI_MAX_RETRIES` environment variable or set to 5.
         :param generation_kwargs: Other parameters to use for the model. These parameters are all sent directly to
             the OpenAI endpoint. See OpenAI [documentation](https://platform.openai.com/docs/api-reference/chat) for
             more details.
@@ -140,7 +145,8 @@
         self.azure_deployment = azure_deployment
         self.organization = organization
         self.model = azure_deployment or "gpt-35-turbo"
-        self.timeout = timeout
+        self.timeout = timeout or float(os.environ.get("OPENAI_TIMEOUT", 30.0))
+        self.max_retries = max_retries or int(os.environ.get("OPENAI_MAX_RETRIES", 5))
 
         self.client = AzureOpenAI(
             api_version=api_version,
@@ -149,6 +155,8 @@
             api_key=api_key.resolve_value() if api_key is not None else None,
             azure_ad_token=azure_ad_token.resolve_value() if azure_ad_token is not None else None,
             organization=organization,
+            timeout=self.timeout,
+            max_retries=self.max_retries,
         )
 
     def to_dict(self) -> Dict[str, Any]:
@@ -168,6 +176,7 @@
             streaming_callback=callback_name,
             generation_kwargs=self.generation_kwargs,
             timeout=self.timeout,
+            max_retries=self.max_retries,
             api_key=self.api_key.to_dict() if self.api_key is not None else None,
             azure_ad_token=self.azure_ad_token.to_dict() if self.azure_ad_token is not None else None,
         )

{"golden_diff": "diff --git a/haystack/components/generators/chat/azure.py b/haystack/components/generators/chat/azure.py\n--- a/haystack/components/generators/chat/azure.py\n+++ b/haystack/components/generators/chat/azure.py\n@@ -81,6 +81,7 @@\n         organization: Optional[str] = None,\n         streaming_callback: Optional[Callable[[StreamingChunk], None]] = None,\n         timeout: Optional[float] = None,\n+        max_retries: Optional[int] = None,\n         generation_kwargs: Optional[Dict[str, Any]] = None,\n     ):\n         \"\"\"\n@@ -95,6 +96,10 @@\n         [production best practices](https://platform.openai.com/docs/guides/production-best-practices/setting-up-your-organization).\n         :param streaming_callback: A callback function that is called when a new token is received from the stream.\n             The callback function accepts StreamingChunk as an argument.\n+        :param timeout: The timeout in seconds to be passed to the underlying `AzureOpenAI` client, if not set it is\n+            inferred from the `OPENAI_TIMEOUT` environment variable or set to 30.\n+        :param max_retries: Maximum retries to establish a connection with AzureOpenAI if it returns an internal error,\n+            if not set it is inferred from the `OPENAI_MAX_RETRIES` environment variable or set to 5.\n         :param generation_kwargs: Other parameters to use for the model. These parameters are all sent directly to\n             the OpenAI endpoint. See OpenAI [documentation](https://platform.openai.com/docs/api-reference/chat) for\n             more details.\n@@ -140,7 +145,8 @@\n         self.azure_deployment = azure_deployment\n         self.organization = organization\n         self.model = azure_deployment or \"gpt-35-turbo\"\n-        self.timeout = timeout\n+        self.timeout = timeout or float(os.environ.get(\"OPENAI_TIMEOUT\", 30.0))\n+        self.max_retries = max_retries or int(os.environ.get(\"OPENAI_MAX_RETRIES\", 5))\n \n         self.client = AzureOpenAI(\n             api_version=api_version,\n@@ -149,6 +155,8 @@\n             api_key=api_key.resolve_value() if api_key is not None else None,\n             azure_ad_token=azure_ad_token.resolve_value() if azure_ad_token is not None else None,\n             organization=organization,\n+            timeout=self.timeout,\n+            max_retries=self.max_retries,\n         )\n \n     def to_dict(self) -> Dict[str, Any]:\n@@ -168,6 +176,7 @@\n             streaming_callback=callback_name,\n             generation_kwargs=self.generation_kwargs,\n             timeout=self.timeout,\n+            max_retries=self.max_retries,\n             api_key=self.api_key.to_dict() if self.api_key is not None else None,\n             azure_ad_token=self.azure_ad_token.to_dict() if self.azure_ad_token is not None else None,\n         )\n", "issue": "Add `max_retries` and `timeout` params to all `AzureOpenAI` classes\n**Is your feature request related to a problem? Please describe.**\r\n\r\nCurrently all `OpenAI` related classes (e.g. `OpenAIDocumentEmbedder`, `OpenAIChatGenerator`) can be initialised by setting `max_retries` and `timeout` params.\r\n\r\nThe corresponding `AzureOpenAI` don't always have the same params.\r\n\r\n**Describe the solution you'd like**\r\n\r\nIt would be nice to have these params in the `AzureOpenAI` classes\r\n\r\n**Describe alternatives you've considered**\r\n\r\nSubclass `AzureOpenAI` and create custom components.\r\n\r\n**Additional context**\r\n\r\ncc @anakin87 :)\n", "before_files": [{"content": "# SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport os\nfrom typing import Any, Callable, Dict, Optional\n\n# pylint: disable=import-error\nfrom openai.lib.azure import AzureOpenAI\n\nfrom haystack import component, default_from_dict, default_to_dict, logging\nfrom haystack.components.generators.chat import OpenAIChatGenerator\nfrom haystack.dataclasses import StreamingChunk\nfrom haystack.utils import Secret, deserialize_callable, deserialize_secrets_inplace, serialize_callable\n\nlogger = logging.getLogger(__name__)\n\n\n@component\nclass AzureOpenAIChatGenerator(OpenAIChatGenerator):\n    \"\"\"\n    A Chat Generator component that uses the Azure OpenAI API to generate text.\n\n    Enables text generation using OpenAI's large language models (LLMs) on Azure. It supports `gpt-4` and\n    `gpt-3.5-turbo` family of models accessed through the chat completions API endpoint.\n\n    Users can pass any text generation parameters valid for the `openai.ChatCompletion.create` method\n    directly to this component via the `generation_kwargs` parameter in `__init__` or the `generation_kwargs`\n    parameter in `run` method.\n\n    For more details on OpenAI models deployed on Azure, refer to the Microsoft\n    [documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/).\n\n    Key Features and Compatibility:\n     - Primary Compatibility: Designed to work seamlessly with the OpenAI API Chat Completion endpoint.\n     - Streaming Support: Supports streaming responses from the OpenAI API Chat Completion endpoint.\n     - Customizability: Supports all parameters supported by the OpenAI API Chat Completion endpoint.\n\n    Input and Output Format:\n      - ChatMessage Format: This component uses the ChatMessage format for structuring both input and output, ensuring\n        coherent and contextually relevant responses in chat-based text generation scenarios.\n     - Details on the ChatMessage format can be found [here](https://docs.haystack.deepset.ai/v2.0/docs/data-classes#chatmessage).\n\n\n    Usage example:\n\n    ```python\n    from haystack.components.generators.chat import AzureOpenAIGenerator\n    from haystack.dataclasses import ChatMessage\n    from haystack.utils import Secret\n\n    messages = [ChatMessage.from_user(\"What's Natural Language Processing?\")]\n\n    client = AzureOpenAIGenerator(\n        azure_endpoint=\"<Your Azure endpoint e.g. `https://your-company.azure.openai.com/>\",\n        api_key=Secret.from_token(\"<your-api-key>\"),\n        azure_deployment=\"<this a model name, e.g. gpt-35-turbo>\")\n    response = client.run(messages)\n    print(response)\n    ```\n\n    ```\n    {'replies':\n        [ChatMessage(content='Natural Language Processing (NLP) is a branch of artificial intelligence that focuses on\n         enabling computers to understand, interpret, and generate human language in a way that is useful.',\n         role=<ChatRole.ASSISTANT: 'assistant'>, name=None,\n         meta={'model': 'gpt-3.5-turbo-0613', 'index': 0, 'finish_reason': 'stop',\n         'usage': {'prompt_tokens': 15, 'completion_tokens': 36, 'total_tokens': 51}})]\n    }\n    ```\n    \"\"\"\n\n    # pylint: disable=super-init-not-called\n    def __init__(\n        self,\n        azure_endpoint: Optional[str] = None,\n        api_version: Optional[str] = \"2023-05-15\",\n        azure_deployment: Optional[str] = \"gpt-35-turbo\",\n        api_key: Optional[Secret] = Secret.from_env_var(\"AZURE_OPENAI_API_KEY\", strict=False),\n        azure_ad_token: Optional[Secret] = Secret.from_env_var(\"AZURE_OPENAI_AD_TOKEN\", strict=False),\n        organization: Optional[str] = None,\n        streaming_callback: Optional[Callable[[StreamingChunk], None]] = None,\n        timeout: Optional[float] = None,\n        generation_kwargs: Optional[Dict[str, Any]] = None,\n    ):\n        \"\"\"\n        Initialize the Azure OpenAI Chat Generator component.\n\n        :param azure_endpoint: The endpoint of the deployed model, e.g. `\"https://example-resource.azure.openai.com/\"`\n        :param api_version: The version of the API to use. Defaults to 2023-05-15\n        :param azure_deployment: The deployment of the model, usually the model name.\n        :param api_key: The API key to use for authentication.\n        :param azure_ad_token: [Azure Active Directory token](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id)\n        :param organization: The Organization ID, defaults to `None`. See\n        [production best practices](https://platform.openai.com/docs/guides/production-best-practices/setting-up-your-organization).\n        :param streaming_callback: A callback function that is called when a new token is received from the stream.\n            The callback function accepts StreamingChunk as an argument.\n        :param generation_kwargs: Other parameters to use for the model. These parameters are all sent directly to\n            the OpenAI endpoint. See OpenAI [documentation](https://platform.openai.com/docs/api-reference/chat) for\n            more details.\n            Some of the supported parameters:\n            - `max_tokens`: The maximum number of tokens the output text can have.\n            - `temperature`: What sampling temperature to use. Higher values mean the model will take more risks.\n                Try 0.9 for more creative applications and 0 (argmax sampling) for ones with a well-defined answer.\n            - `top_p`: An alternative to sampling with temperature, called nucleus sampling, where the model\n                considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens\n                comprising the top 10% probability mass are considered.\n            - `n`: How many completions to generate for each prompt. For example, if the LLM gets 3 prompts and n is 2,\n                it will generate two completions for each of the three prompts, ending up with 6 completions in total.\n            - `stop`: One or more sequences after which the LLM should stop generating tokens.\n            - `presence_penalty`: What penalty to apply if a token is already present at all. Bigger values mean\n                the model will be less likely to repeat the same token in the text.\n            - `frequency_penalty`: What penalty to apply if a token has already been generated in the text.\n                Bigger values mean the model will be less likely to repeat the same token in the text.\n            - `logit_bias`: Add a logit bias to specific tokens. The keys of the dictionary are tokens, and the\n                values are the bias to add to that token.\n        \"\"\"\n        # We intentionally do not call super().__init__ here because we only need to instantiate the client to interact\n        # with the API.\n\n        # Why is this here?\n        # AzureOpenAI init is forcing us to use an init method that takes either base_url or azure_endpoint as not\n        # None init parameters. This way we accommodate the use case where env var AZURE_OPENAI_ENDPOINT is set instead\n        # of passing it as a parameter.\n        azure_endpoint = azure_endpoint or os.environ.get(\"AZURE_OPENAI_ENDPOINT\")\n        if not azure_endpoint:\n            raise ValueError(\"Please provide an Azure endpoint or set the environment variable AZURE_OPENAI_ENDPOINT.\")\n\n        if api_key is None and azure_ad_token is None:\n            raise ValueError(\"Please provide an API key or an Azure Active Directory token.\")\n\n        # The check above makes mypy incorrectly infer that api_key is never None,\n        # which propagates the incorrect type.\n        self.api_key = api_key  # type: ignore\n        self.azure_ad_token = azure_ad_token\n        self.generation_kwargs = generation_kwargs or {}\n        self.streaming_callback = streaming_callback\n        self.api_version = api_version\n        self.azure_endpoint = azure_endpoint\n        self.azure_deployment = azure_deployment\n        self.organization = organization\n        self.model = azure_deployment or \"gpt-35-turbo\"\n        self.timeout = timeout\n\n        self.client = AzureOpenAI(\n            api_version=api_version,\n            azure_endpoint=azure_endpoint,\n            azure_deployment=azure_deployment,\n            api_key=api_key.resolve_value() if api_key is not None else None,\n            azure_ad_token=azure_ad_token.resolve_value() if azure_ad_token is not None else None,\n            organization=organization,\n        )\n\n    def to_dict(self) -> Dict[str, Any]:\n        \"\"\"\n        Serialize this component to a dictionary.\n\n        :returns:\n            The serialized component as a dictionary.\n        \"\"\"\n        callback_name = serialize_callable(self.streaming_callback) if self.streaming_callback else None\n        return default_to_dict(\n            self,\n            azure_endpoint=self.azure_endpoint,\n            azure_deployment=self.azure_deployment,\n            organization=self.organization,\n            api_version=self.api_version,\n            streaming_callback=callback_name,\n            generation_kwargs=self.generation_kwargs,\n            timeout=self.timeout,\n            api_key=self.api_key.to_dict() if self.api_key is not None else None,\n            azure_ad_token=self.azure_ad_token.to_dict() if self.azure_ad_token is not None else None,\n        )\n\n    @classmethod\n    def from_dict(cls, data: Dict[str, Any]) -> \"AzureOpenAIChatGenerator\":\n        \"\"\"\n        Deserialize this component from a dictionary.\n\n        :param data: The dictionary representation of this component.\n        :returns:\n            The deserialized component instance.\n        \"\"\"\n        deserialize_secrets_inplace(data[\"init_parameters\"], keys=[\"api_key\", \"azure_ad_token\"])\n        init_params = data.get(\"init_parameters\", {})\n        serialized_callback_handler = init_params.get(\"streaming_callback\")\n        if serialized_callback_handler:\n            data[\"init_parameters\"][\"streaming_callback\"] = deserialize_callable(serialized_callback_handler)\n        return default_from_dict(cls, data)\n", "path": "haystack/components/generators/chat/azure.py"}], "after_files": [{"content": "# SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport os\nfrom typing import Any, Callable, Dict, Optional\n\n# pylint: disable=import-error\nfrom openai.lib.azure import AzureOpenAI\n\nfrom haystack import component, default_from_dict, default_to_dict, logging\nfrom haystack.components.generators.chat import OpenAIChatGenerator\nfrom haystack.dataclasses import StreamingChunk\nfrom haystack.utils import Secret, deserialize_callable, deserialize_secrets_inplace, serialize_callable\n\nlogger = logging.getLogger(__name__)\n\n\n@component\nclass AzureOpenAIChatGenerator(OpenAIChatGenerator):\n    \"\"\"\n    A Chat Generator component that uses the Azure OpenAI API to generate text.\n\n    Enables text generation using OpenAI's large language models (LLMs) on Azure. It supports `gpt-4` and\n    `gpt-3.5-turbo` family of models accessed through the chat completions API endpoint.\n\n    Users can pass any text generation parameters valid for the `openai.ChatCompletion.create` method\n    directly to this component via the `generation_kwargs` parameter in `__init__` or the `generation_kwargs`\n    parameter in `run` method.\n\n    For more details on OpenAI models deployed on Azure, refer to the Microsoft\n    [documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/).\n\n    Key Features and Compatibility:\n     - Primary Compatibility: Designed to work seamlessly with the OpenAI API Chat Completion endpoint.\n     - Streaming Support: Supports streaming responses from the OpenAI API Chat Completion endpoint.\n     - Customizability: Supports all parameters supported by the OpenAI API Chat Completion endpoint.\n\n    Input and Output Format:\n      - ChatMessage Format: This component uses the ChatMessage format for structuring both input and output, ensuring\n        coherent and contextually relevant responses in chat-based text generation scenarios.\n     - Details on the ChatMessage format can be found [here](https://docs.haystack.deepset.ai/v2.0/docs/data-classes#chatmessage).\n\n\n    Usage example:\n\n    ```python\n    from haystack.components.generators.chat import AzureOpenAIGenerator\n    from haystack.dataclasses import ChatMessage\n    from haystack.utils import Secret\n\n    messages = [ChatMessage.from_user(\"What's Natural Language Processing?\")]\n\n    client = AzureOpenAIGenerator(\n        azure_endpoint=\"<Your Azure endpoint e.g. `https://your-company.azure.openai.com/>\",\n        api_key=Secret.from_token(\"<your-api-key>\"),\n        azure_deployment=\"<this a model name, e.g. gpt-35-turbo>\")\n    response = client.run(messages)\n    print(response)\n    ```\n\n    ```\n    {'replies':\n        [ChatMessage(content='Natural Language Processing (NLP) is a branch of artificial intelligence that focuses on\n         enabling computers to understand, interpret, and generate human language in a way that is useful.',\n         role=<ChatRole.ASSISTANT: 'assistant'>, name=None,\n         meta={'model': 'gpt-3.5-turbo-0613', 'index': 0, 'finish_reason': 'stop',\n         'usage': {'prompt_tokens': 15, 'completion_tokens': 36, 'total_tokens': 51}})]\n    }\n    ```\n    \"\"\"\n\n    # pylint: disable=super-init-not-called\n    def __init__(\n        self,\n        azure_endpoint: Optional[str] = None,\n        api_version: Optional[str] = \"2023-05-15\",\n        azure_deployment: Optional[str] = \"gpt-35-turbo\",\n        api_key: Optional[Secret] = Secret.from_env_var(\"AZURE_OPENAI_API_KEY\", strict=False),\n        azure_ad_token: Optional[Secret] = Secret.from_env_var(\"AZURE_OPENAI_AD_TOKEN\", strict=False),\n        organization: Optional[str] = None,\n        streaming_callback: Optional[Callable[[StreamingChunk], None]] = None,\n        timeout: Optional[float] = None,\n        max_retries: Optional[int] = None,\n        generation_kwargs: Optional[Dict[str, Any]] = None,\n    ):\n        \"\"\"\n        Initialize the Azure OpenAI Chat Generator component.\n\n        :param azure_endpoint: The endpoint of the deployed model, e.g. `\"https://example-resource.azure.openai.com/\"`\n        :param api_version: The version of the API to use. Defaults to 2023-05-15\n        :param azure_deployment: The deployment of the model, usually the model name.\n        :param api_key: The API key to use for authentication.\n        :param azure_ad_token: [Azure Active Directory token](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id)\n        :param organization: The Organization ID, defaults to `None`. See\n        [production best practices](https://platform.openai.com/docs/guides/production-best-practices/setting-up-your-organization).\n        :param streaming_callback: A callback function that is called when a new token is received from the stream.\n            The callback function accepts StreamingChunk as an argument.\n        :param timeout: The timeout in seconds to be passed to the underlying `AzureOpenAI` client, if not set it is\n            inferred from the `OPENAI_TIMEOUT` environment variable or set to 30.\n        :param max_retries: Maximum retries to establish a connection with AzureOpenAI if it returns an internal error,\n            if not set it is inferred from the `OPENAI_MAX_RETRIES` environment variable or set to 5.\n        :param generation_kwargs: Other parameters to use for the model. These parameters are all sent directly to\n            the OpenAI endpoint. See OpenAI [documentation](https://platform.openai.com/docs/api-reference/chat) for\n            more details.\n            Some of the supported parameters:\n            - `max_tokens`: The maximum number of tokens the output text can have.\n            - `temperature`: What sampling temperature to use. Higher values mean the model will take more risks.\n                Try 0.9 for more creative applications and 0 (argmax sampling) for ones with a well-defined answer.\n            - `top_p`: An alternative to sampling with temperature, called nucleus sampling, where the model\n                considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens\n                comprising the top 10% probability mass are considered.\n            - `n`: How many completions to generate for each prompt. For example, if the LLM gets 3 prompts and n is 2,\n                it will generate two completions for each of the three prompts, ending up with 6 completions in total.\n            - `stop`: One or more sequences after which the LLM should stop generating tokens.\n            - `presence_penalty`: What penalty to apply if a token is already present at all. Bigger values mean\n                the model will be less likely to repeat the same token in the text.\n            - `frequency_penalty`: What penalty to apply if a token has already been generated in the text.\n                Bigger values mean the model will be less likely to repeat the same token in the text.\n            - `logit_bias`: Add a logit bias to specific tokens. The keys of the dictionary are tokens, and the\n                values are the bias to add to that token.\n        \"\"\"\n        # We intentionally do not call super().__init__ here because we only need to instantiate the client to interact\n        # with the API.\n\n        # Why is this here?\n        # AzureOpenAI init is forcing us to use an init method that takes either base_url or azure_endpoint as not\n        # None init parameters. This way we accommodate the use case where env var AZURE_OPENAI_ENDPOINT is set instead\n        # of passing it as a parameter.\n        azure_endpoint = azure_endpoint or os.environ.get(\"AZURE_OPENAI_ENDPOINT\")\n        if not azure_endpoint:\n            raise ValueError(\"Please provide an Azure endpoint or set the environment variable AZURE_OPENAI_ENDPOINT.\")\n\n        if api_key is None and azure_ad_token is None:\n            raise ValueError(\"Please provide an API key or an Azure Active Directory token.\")\n\n        # The check above makes mypy incorrectly infer that api_key is never None,\n        # which propagates the incorrect type.\n        self.api_key = api_key  # type: ignore\n        self.azure_ad_token = azure_ad_token\n        self.generation_kwargs = generation_kwargs or {}\n        self.streaming_callback = streaming_callback\n        self.api_version = api_version\n        self.azure_endpoint = azure_endpoint\n        self.azure_deployment = azure_deployment\n        self.organization = organization\n        self.model = azure_deployment or \"gpt-35-turbo\"\n        self.timeout = timeout or float(os.environ.get(\"OPENAI_TIMEOUT\", 30.0))\n        self.max_retries = max_retries or int(os.environ.get(\"OPENAI_MAX_RETRIES\", 5))\n\n        self.client = AzureOpenAI(\n            api_version=api_version,\n            azure_endpoint=azure_endpoint,\n            azure_deployment=azure_deployment,\n            api_key=api_key.resolve_value() if api_key is not None else None,\n            azure_ad_token=azure_ad_token.resolve_value() if azure_ad_token is not None else None,\n            organization=organization,\n            timeout=self.timeout,\n            max_retries=self.max_retries,\n        )\n\n    def to_dict(self) -> Dict[str, Any]:\n        \"\"\"\n        Serialize this component to a dictionary.\n\n        :returns:\n            The serialized component as a dictionary.\n        \"\"\"\n        callback_name = serialize_callable(self.streaming_callback) if self.streaming_callback else None\n        return default_to_dict(\n            self,\n            azure_endpoint=self.azure_endpoint,\n            azure_deployment=self.azure_deployment,\n            organization=self.organization,\n            api_version=self.api_version,\n            streaming_callback=callback_name,\n            generation_kwargs=self.generation_kwargs,\n            timeout=self.timeout,\n            max_retries=self.max_retries,\n            api_key=self.api_key.to_dict() if self.api_key is not None else None,\n            azure_ad_token=self.azure_ad_token.to_dict() if self.azure_ad_token is not None else None,\n        )\n\n    @classmethod\n    def from_dict(cls, data: Dict[str, Any]) -> \"AzureOpenAIChatGenerator\":\n        \"\"\"\n        Deserialize this component from a dictionary.\n\n        :param data: The dictionary representation of this component.\n        :returns:\n            The deserialized component instance.\n        \"\"\"\n        deserialize_secrets_inplace(data[\"init_parameters\"], keys=[\"api_key\", \"azure_ad_token\"])\n        init_params = data.get(\"init_parameters\", {})\n        serialized_callback_handler = init_params.get(\"streaming_callback\")\n        if serialized_callback_handler:\n            data[\"init_parameters\"][\"streaming_callback\"] = deserialize_callable(serialized_callback_handler)\n        return default_from_dict(cls, data)\n", "path": "haystack/components/generators/chat/azure.py"}]}