We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Set `openai.api_key` if `OPENAI_API_KEY` exists
### Summary

The line that needs a fix:

https://github.com/mlflow/mlflow/blob/a4db4ee826765f0365944f83124af8840c72f4d8/mlflow/openai/utils.py#L161

Just because `"OPENAI_API_KEY" in os.environ` is True doesn't mean `openai.api_key` is set. The following code currently doens't work.

```python
import os

assert "OPENAI_API_KEY" not in os.environ

import openai

# Set OPENAI_API_KEY after openai is imported
os.environ["OPENAI_API_KEY"] = "..."

basic_qa_model = mlflow.openai.log_model(
    model="gpt-3.5-turbo",
    task=openai.ChatCompletion,
    artifact_path="model",
    messages=[
        {"role": "user", "content": "{question}"},
    ],
)
loaded_model = mlflow.pyfunc.load_model(basic_qa_model.model_uri)
loaded_model.predict(["What is MLflow"])  # this line throws because `openai.api_key` is None
```

### Notes

- Make sure to open a PR from a **non-master** branch.
- Sign off the commit using the `-s` flag when making a commit:

  ```sh
  git commit -s -m "..."
           # ^^ make sure to use this
  ```

- Include `#{issue_number}` (e.g. `#123`) in the PR description when opening a PR.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mlflow/openai/utils.py`
Content:
```
1 import json
2 import os
3 import time
4 from contextlib import contextmanager
5 from unittest import mock
6 
7 import requests
8 
9 import mlflow
10 
11 TEST_CONTENT = "test"
12 
13 TEST_SOURCE_DOCUMENTS = [
14     {
15         "page_content": "We see the unity among leaders ...",
16         "metadata": {"source": "tests/langchain/state_of_the_union.txt"},
17     },
18 ]
19 TEST_INTERMEDIATE_STEPS = (
20     [
21         {
22             "tool": "Search",
23             "tool_input": "High temperature in SF yesterday",
24             "log": " I need to find the temperature first...",
25             "result": "San Francisco...",
26         },
27     ],
28 )
29 
30 
31 class _MockResponse:
32     def __init__(self, status_code, json_data):
33         self.status_code = status_code
34         self.content = json.dumps(json_data).encode()
35         self.headers = {"Content-Type": "application/json"}
36         self.text = mlflow.__version__
37 
38 
39 def _chat_completion_json_sample(content):
40     # https://platform.openai.com/docs/api-reference/chat/create
41     return {
42         "id": "chatcmpl-123",
43         "object": "chat.completion",
44         "created": 1677652288,
45         "choices": [
46             {
47                 "index": 0,
48                 "message": {"role": "assistant", "content": content},
49                 "finish_reason": "stop",
50                 "text": content,
51             }
52         ],
53         "usage": {"prompt_tokens": 9, "completion_tokens": 12, "total_tokens": 21},
54     }
55 
56 
57 def _completion_json_sample(content):
58     return {
59         "id": "cmpl-123",
60         "object": "text_completion",
61         "created": 1589478378,
62         "model": "text-davinci-003",
63         "choices": [{"text": content, "index": 0, "finish_reason": "length"}],
64         "usage": {"prompt_tokens": 5, "completion_tokens": 7, "total_tokens": 12},
65     }
66 
67 
68 def _models_retrieve_json_sample():
69     # https://platform.openai.com/docs/api-reference/models/retrieve
70     return {
71         "id": "gpt-3.5-turbo",
72         "object": "model",
73         "owned_by": "openai",
74         "permission": [],
75     }
76 
77 
78 def _mock_chat_completion_response(content=TEST_CONTENT):
79     return _MockResponse(200, _chat_completion_json_sample(content))
80 
81 
82 def _mock_completion_response(content=TEST_CONTENT):
83     return _MockResponse(200, _completion_json_sample(content))
84 
85 
86 def _mock_embeddings_response(num_texts):
87     return _MockResponse(
88         200,
89         {
90             "object": "list",
91             "data": [
92                 {
93                     "object": "embedding",
94                     "embedding": [
95                         0.0,
96                     ],
97                     "index": i,
98                 }
99                 for i in range(num_texts)
100             ],
101             "model": "text-embedding-ada-002",
102             "usage": {"prompt_tokens": 8, "total_tokens": 8},
103         },
104     )
105 
106 
107 def _mock_models_retrieve_response():
108     return _MockResponse(200, _models_retrieve_json_sample())
109 
110 
111 @contextmanager
112 def _mock_request(**kwargs):
113     with mock.patch("requests.Session.request", **kwargs) as m:
114         yield m
115 
116 
117 def _mock_openai_request():
118     original = requests.Session.request
119 
120     def request(*args, **kwargs):
121         url = args[2] if len(args) > 2 else kwargs.get("url")
122 
123         if url.endswith("/chat/completions"):
124             messages = json.loads(kwargs.get("data")).get("messages")
125             return _mock_chat_completion_response(content=json.dumps(messages))
126         elif url.endswith("/completions"):
127             prompt = json.loads(kwargs.get("data")).get("prompt")
128             return _mock_completion_response(content=json.dumps(prompt))
129         elif url.endswith("/embeddings"):
130             inp = json.loads(kwargs.get("data")).get("input")
131             return _mock_embeddings_response(len(inp) if isinstance(inp, list) else 1)
132         else:
133             return original(*args, **kwargs)
134 
135     return _mock_request(new=request)
136 
137 
138 def _validate_model_params(task, model, params):
139     if not params:
140         return
141 
142     if any(key in model for key in params):
143         raise mlflow.MlflowException.invalid_parameter_value(
144             f"Providing any of {list(model.keys())} as parameters in the signature is not "
145             "allowed because they were indicated as part of the OpenAI model. Either remove "
146             "the argument when logging the model or remove the parameter from the signature.",
147         )
148     if "batch_size" in params and task == "chat.completions":
149         raise mlflow.MlflowException.invalid_parameter_value(
150             "Parameter `batch_size` is not supported for task `chat.completions`"
151         )
152 
153 
154 class _OAITokenHolder:
155     def __init__(self, api_type):
156         import openai
157 
158         self._api_token = None
159         self._credential = None
160         self._is_azure_ad = api_type in ("azure_ad", "azuread")
161         self._key_configured = bool(openai.api_key) or "OPENAI_API_KEY" in os.environ
162 
163         if self._is_azure_ad and not self._key_configured:
164             try:
165                 from azure.identity import DefaultAzureCredential
166             except ImportError:
167                 raise mlflow.MlflowException(
168                     "Using API type `azure_ad` or `azuread` requires the package"
169                     " `azure-identity` to be installed."
170                 )
171             self._credential = DefaultAzureCredential()
172 
173     def validate(self, logger=None):
174         """
175         Validates the token or API key configured for accessing the OpenAI resource.
176         """
177         import openai
178 
179         if self._key_configured:
180             return
181 
182         if self._is_azure_ad:
183             if not self._api_token or self._api_token.expires_on < time.time() + 60:
184                 from azure.core.exceptions import ClientAuthenticationError
185 
186                 if logger:
187                     logger.debug(
188                         "Token for Azure AD is either expired or unset. Attempting to "
189                         "acquire a new token."
190                     )
191                 try:
192                     self._api_token = self._credential.get_token(
193                         "https://cognitiveservices.azure.com/.default"
194                     )
195                 except ClientAuthenticationError as err:
196                     raise mlflow.MlflowException(
197                         "Unable to acquire a valid Azure AD token for the resource due to "
198                         f"the following error: {err.message}"
199                     ) from err
200                 openai.api_key = self._api_token.token
201             if logger:
202                 logger.debug("Token refreshed successfully")
203         else:
204             raise mlflow.MlflowException(
205                 "OpenAI API key must be set in the ``OPENAI_API_KEY`` environment variable."
206             )
207
```
--- 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/mlflow/openai/utils.py b/mlflow/openai/utils.py
--- a/mlflow/openai/utils.py
+++ b/mlflow/openai/utils.py
@@ -158,7 +158,13 @@
         self._api_token = None
         self._credential = None
         self._is_azure_ad = api_type in ("azure_ad", "azuread")
-        self._key_configured = bool(openai.api_key) or "OPENAI_API_KEY" in os.environ
+        self._key_configured = bool(openai.api_key)
+
+        # set the api key if it's not set. this is to deal with cases where the
+        # user sets the environment variable after importing the `openai` module
+        if not bool(openai.api_key) and "OPENAI_API_KEY" in os.environ:
+            openai.api_key = os.environ["OPENAI_API_KEY"]
+            self._key_configured = True
 
         if self._is_azure_ad and not self._key_configured:
             try:

{"golden_diff": "diff --git a/mlflow/openai/utils.py b/mlflow/openai/utils.py\n--- a/mlflow/openai/utils.py\n+++ b/mlflow/openai/utils.py\n@@ -158,7 +158,13 @@\n         self._api_token = None\n         self._credential = None\n         self._is_azure_ad = api_type in (\"azure_ad\", \"azuread\")\n-        self._key_configured = bool(openai.api_key) or \"OPENAI_API_KEY\" in os.environ\n+        self._key_configured = bool(openai.api_key)\n+\n+        # set the api key if it's not set. this is to deal with cases where the\n+        # user sets the environment variable after importing the `openai` module\n+        if not bool(openai.api_key) and \"OPENAI_API_KEY\" in os.environ:\n+            openai.api_key = os.environ[\"OPENAI_API_KEY\"]\n+            self._key_configured = True\n \n         if self._is_azure_ad and not self._key_configured:\n             try:\n", "issue": "Set `openai.api_key` if `OPENAI_API_KEY` exists\n### Summary\r\n\r\nThe line that needs a fix:\r\n\r\nhttps://github.com/mlflow/mlflow/blob/a4db4ee826765f0365944f83124af8840c72f4d8/mlflow/openai/utils.py#L161\r\n\r\nJust because `\"OPENAI_API_KEY\" in os.environ` is True doesn't mean `openai.api_key` is set. The following code currently doens't work.\r\n\r\n```python\r\nimport os\r\n\r\nassert \"OPENAI_API_KEY\" not in os.environ\r\n\r\nimport openai\r\n\r\n# Set OPENAI_API_KEY after openai is imported\r\nos.environ[\"OPENAI_API_KEY\"] = \"...\"\r\n\r\nbasic_qa_model = mlflow.openai.log_model(\r\n    model=\"gpt-3.5-turbo\",\r\n    task=openai.ChatCompletion,\r\n    artifact_path=\"model\",\r\n    messages=[\r\n        {\"role\": \"user\", \"content\": \"{question}\"},\r\n    ],\r\n)\r\nloaded_model = mlflow.pyfunc.load_model(basic_qa_model.model_uri)\r\nloaded_model.predict([\"What is MLflow\"])  # this line throws because `openai.api_key` is None\r\n```\r\n\r\n### Notes\r\n\r\n- Make sure to open a PR from a **non-master** branch.\r\n- Sign off the commit using the `-s` flag when making a commit:\r\n\r\n  ```sh\r\n  git commit -s -m \"...\"\r\n           # ^^ make sure to use this\r\n  ```\r\n\r\n- Include `#{issue_number}` (e.g. `#123`) in the PR description when opening a PR.\r\n\n", "before_files": [{"content": "import json\nimport os\nimport time\nfrom contextlib import contextmanager\nfrom unittest import mock\n\nimport requests\n\nimport mlflow\n\nTEST_CONTENT = \"test\"\n\nTEST_SOURCE_DOCUMENTS = [\n    {\n        \"page_content\": \"We see the unity among leaders ...\",\n        \"metadata\": {\"source\": \"tests/langchain/state_of_the_union.txt\"},\n    },\n]\nTEST_INTERMEDIATE_STEPS = (\n    [\n        {\n            \"tool\": \"Search\",\n            \"tool_input\": \"High temperature in SF yesterday\",\n            \"log\": \" I need to find the temperature first...\",\n            \"result\": \"San Francisco...\",\n        },\n    ],\n)\n\n\nclass _MockResponse:\n    def __init__(self, status_code, json_data):\n        self.status_code = status_code\n        self.content = json.dumps(json_data).encode()\n        self.headers = {\"Content-Type\": \"application/json\"}\n        self.text = mlflow.__version__\n\n\ndef _chat_completion_json_sample(content):\n    # https://platform.openai.com/docs/api-reference/chat/create\n    return {\n        \"id\": \"chatcmpl-123\",\n        \"object\": \"chat.completion\",\n        \"created\": 1677652288,\n        \"choices\": [\n            {\n                \"index\": 0,\n                \"message\": {\"role\": \"assistant\", \"content\": content},\n                \"finish_reason\": \"stop\",\n                \"text\": content,\n            }\n        ],\n        \"usage\": {\"prompt_tokens\": 9, \"completion_tokens\": 12, \"total_tokens\": 21},\n    }\n\n\ndef _completion_json_sample(content):\n    return {\n        \"id\": \"cmpl-123\",\n        \"object\": \"text_completion\",\n        \"created\": 1589478378,\n        \"model\": \"text-davinci-003\",\n        \"choices\": [{\"text\": content, \"index\": 0, \"finish_reason\": \"length\"}],\n        \"usage\": {\"prompt_tokens\": 5, \"completion_tokens\": 7, \"total_tokens\": 12},\n    }\n\n\ndef _models_retrieve_json_sample():\n    # https://platform.openai.com/docs/api-reference/models/retrieve\n    return {\n        \"id\": \"gpt-3.5-turbo\",\n        \"object\": \"model\",\n        \"owned_by\": \"openai\",\n        \"permission\": [],\n    }\n\n\ndef _mock_chat_completion_response(content=TEST_CONTENT):\n    return _MockResponse(200, _chat_completion_json_sample(content))\n\n\ndef _mock_completion_response(content=TEST_CONTENT):\n    return _MockResponse(200, _completion_json_sample(content))\n\n\ndef _mock_embeddings_response(num_texts):\n    return _MockResponse(\n        200,\n        {\n            \"object\": \"list\",\n            \"data\": [\n                {\n                    \"object\": \"embedding\",\n                    \"embedding\": [\n                        0.0,\n                    ],\n                    \"index\": i,\n                }\n                for i in range(num_texts)\n            ],\n            \"model\": \"text-embedding-ada-002\",\n            \"usage\": {\"prompt_tokens\": 8, \"total_tokens\": 8},\n        },\n    )\n\n\ndef _mock_models_retrieve_response():\n    return _MockResponse(200, _models_retrieve_json_sample())\n\n\n@contextmanager\ndef _mock_request(**kwargs):\n    with mock.patch(\"requests.Session.request\", **kwargs) as m:\n        yield m\n\n\ndef _mock_openai_request():\n    original = requests.Session.request\n\n    def request(*args, **kwargs):\n        url = args[2] if len(args) > 2 else kwargs.get(\"url\")\n\n        if url.endswith(\"/chat/completions\"):\n            messages = json.loads(kwargs.get(\"data\")).get(\"messages\")\n            return _mock_chat_completion_response(content=json.dumps(messages))\n        elif url.endswith(\"/completions\"):\n            prompt = json.loads(kwargs.get(\"data\")).get(\"prompt\")\n            return _mock_completion_response(content=json.dumps(prompt))\n        elif url.endswith(\"/embeddings\"):\n            inp = json.loads(kwargs.get(\"data\")).get(\"input\")\n            return _mock_embeddings_response(len(inp) if isinstance(inp, list) else 1)\n        else:\n            return original(*args, **kwargs)\n\n    return _mock_request(new=request)\n\n\ndef _validate_model_params(task, model, params):\n    if not params:\n        return\n\n    if any(key in model for key in params):\n        raise mlflow.MlflowException.invalid_parameter_value(\n            f\"Providing any of {list(model.keys())} as parameters in the signature is not \"\n            \"allowed because they were indicated as part of the OpenAI model. Either remove \"\n            \"the argument when logging the model or remove the parameter from the signature.\",\n        )\n    if \"batch_size\" in params and task == \"chat.completions\":\n        raise mlflow.MlflowException.invalid_parameter_value(\n            \"Parameter `batch_size` is not supported for task `chat.completions`\"\n        )\n\n\nclass _OAITokenHolder:\n    def __init__(self, api_type):\n        import openai\n\n        self._api_token = None\n        self._credential = None\n        self._is_azure_ad = api_type in (\"azure_ad\", \"azuread\")\n        self._key_configured = bool(openai.api_key) or \"OPENAI_API_KEY\" in os.environ\n\n        if self._is_azure_ad and not self._key_configured:\n            try:\n                from azure.identity import DefaultAzureCredential\n            except ImportError:\n                raise mlflow.MlflowException(\n                    \"Using API type `azure_ad` or `azuread` requires the package\"\n                    \" `azure-identity` to be installed.\"\n                )\n            self._credential = DefaultAzureCredential()\n\n    def validate(self, logger=None):\n        \"\"\"\n        Validates the token or API key configured for accessing the OpenAI resource.\n        \"\"\"\n        import openai\n\n        if self._key_configured:\n            return\n\n        if self._is_azure_ad:\n            if not self._api_token or self._api_token.expires_on < time.time() + 60:\n                from azure.core.exceptions import ClientAuthenticationError\n\n                if logger:\n                    logger.debug(\n                        \"Token for Azure AD is either expired or unset. Attempting to \"\n                        \"acquire a new token.\"\n                    )\n                try:\n                    self._api_token = self._credential.get_token(\n                        \"https://cognitiveservices.azure.com/.default\"\n                    )\n                except ClientAuthenticationError as err:\n                    raise mlflow.MlflowException(\n                        \"Unable to acquire a valid Azure AD token for the resource due to \"\n                        f\"the following error: {err.message}\"\n                    ) from err\n                openai.api_key = self._api_token.token\n            if logger:\n                logger.debug(\"Token refreshed successfully\")\n        else:\n            raise mlflow.MlflowException(\n                \"OpenAI API key must be set in the ``OPENAI_API_KEY`` environment variable.\"\n            )\n", "path": "mlflow/openai/utils.py"}], "after_files": [{"content": "import json\nimport os\nimport time\nfrom contextlib import contextmanager\nfrom unittest import mock\n\nimport requests\n\nimport mlflow\n\nTEST_CONTENT = \"test\"\n\nTEST_SOURCE_DOCUMENTS = [\n    {\n        \"page_content\": \"We see the unity among leaders ...\",\n        \"metadata\": {\"source\": \"tests/langchain/state_of_the_union.txt\"},\n    },\n]\nTEST_INTERMEDIATE_STEPS = (\n    [\n        {\n            \"tool\": \"Search\",\n            \"tool_input\": \"High temperature in SF yesterday\",\n            \"log\": \" I need to find the temperature first...\",\n            \"result\": \"San Francisco...\",\n        },\n    ],\n)\n\n\nclass _MockResponse:\n    def __init__(self, status_code, json_data):\n        self.status_code = status_code\n        self.content = json.dumps(json_data).encode()\n        self.headers = {\"Content-Type\": \"application/json\"}\n        self.text = mlflow.__version__\n\n\ndef _chat_completion_json_sample(content):\n    # https://platform.openai.com/docs/api-reference/chat/create\n    return {\n        \"id\": \"chatcmpl-123\",\n        \"object\": \"chat.completion\",\n        \"created\": 1677652288,\n        \"choices\": [\n            {\n                \"index\": 0,\n                \"message\": {\"role\": \"assistant\", \"content\": content},\n                \"finish_reason\": \"stop\",\n                \"text\": content,\n            }\n        ],\n        \"usage\": {\"prompt_tokens\": 9, \"completion_tokens\": 12, \"total_tokens\": 21},\n    }\n\n\ndef _completion_json_sample(content):\n    return {\n        \"id\": \"cmpl-123\",\n        \"object\": \"text_completion\",\n        \"created\": 1589478378,\n        \"model\": \"text-davinci-003\",\n        \"choices\": [{\"text\": content, \"index\": 0, \"finish_reason\": \"length\"}],\n        \"usage\": {\"prompt_tokens\": 5, \"completion_tokens\": 7, \"total_tokens\": 12},\n    }\n\n\ndef _models_retrieve_json_sample():\n    # https://platform.openai.com/docs/api-reference/models/retrieve\n    return {\n        \"id\": \"gpt-3.5-turbo\",\n        \"object\": \"model\",\n        \"owned_by\": \"openai\",\n        \"permission\": [],\n    }\n\n\ndef _mock_chat_completion_response(content=TEST_CONTENT):\n    return _MockResponse(200, _chat_completion_json_sample(content))\n\n\ndef _mock_completion_response(content=TEST_CONTENT):\n    return _MockResponse(200, _completion_json_sample(content))\n\n\ndef _mock_embeddings_response(num_texts):\n    return _MockResponse(\n        200,\n        {\n            \"object\": \"list\",\n            \"data\": [\n                {\n                    \"object\": \"embedding\",\n                    \"embedding\": [\n                        0.0,\n                    ],\n                    \"index\": i,\n                }\n                for i in range(num_texts)\n            ],\n            \"model\": \"text-embedding-ada-002\",\n            \"usage\": {\"prompt_tokens\": 8, \"total_tokens\": 8},\n        },\n    )\n\n\ndef _mock_models_retrieve_response():\n    return _MockResponse(200, _models_retrieve_json_sample())\n\n\n@contextmanager\ndef _mock_request(**kwargs):\n    with mock.patch(\"requests.Session.request\", **kwargs) as m:\n        yield m\n\n\ndef _mock_openai_request():\n    original = requests.Session.request\n\n    def request(*args, **kwargs):\n        url = args[2] if len(args) > 2 else kwargs.get(\"url\")\n\n        if url.endswith(\"/chat/completions\"):\n            messages = json.loads(kwargs.get(\"data\")).get(\"messages\")\n            return _mock_chat_completion_response(content=json.dumps(messages))\n        elif url.endswith(\"/completions\"):\n            prompt = json.loads(kwargs.get(\"data\")).get(\"prompt\")\n            return _mock_completion_response(content=json.dumps(prompt))\n        elif url.endswith(\"/embeddings\"):\n            inp = json.loads(kwargs.get(\"data\")).get(\"input\")\n            return _mock_embeddings_response(len(inp) if isinstance(inp, list) else 1)\n        else:\n            return original(*args, **kwargs)\n\n    return _mock_request(new=request)\n\n\ndef _validate_model_params(task, model, params):\n    if not params:\n        return\n\n    if any(key in model for key in params):\n        raise mlflow.MlflowException.invalid_parameter_value(\n            f\"Providing any of {list(model.keys())} as parameters in the signature is not \"\n            \"allowed because they were indicated as part of the OpenAI model. Either remove \"\n            \"the argument when logging the model or remove the parameter from the signature.\",\n        )\n    if \"batch_size\" in params and task == \"chat.completions\":\n        raise mlflow.MlflowException.invalid_parameter_value(\n            \"Parameter `batch_size` is not supported for task `chat.completions`\"\n        )\n\n\nclass _OAITokenHolder:\n    def __init__(self, api_type):\n        import openai\n\n        self._api_token = None\n        self._credential = None\n        self._is_azure_ad = api_type in (\"azure_ad\", \"azuread\")\n        self._key_configured = bool(openai.api_key)\n\n        # set the api key if it's not set. this is to deal with cases where the\n        # user sets the environment variable after importing the `openai` module\n        if not bool(openai.api_key) and \"OPENAI_API_KEY\" in os.environ:\n            openai.api_key = os.environ[\"OPENAI_API_KEY\"]\n            self._key_configured = True\n\n        if self._is_azure_ad and not self._key_configured:\n            try:\n                from azure.identity import DefaultAzureCredential\n            except ImportError:\n                raise mlflow.MlflowException(\n                    \"Using API type `azure_ad` or `azuread` requires the package\"\n                    \" `azure-identity` to be installed.\"\n                )\n            self._credential = DefaultAzureCredential()\n\n    def validate(self, logger=None):\n        \"\"\"\n        Validates the token or API key configured for accessing the OpenAI resource.\n        \"\"\"\n        import openai\n\n        if self._key_configured:\n            return\n\n        if self._is_azure_ad:\n            if not self._api_token or self._api_token.expires_on < time.time() + 60:\n                from azure.core.exceptions import ClientAuthenticationError\n\n                if logger:\n                    logger.debug(\n                        \"Token for Azure AD is either expired or unset. Attempting to \"\n                        \"acquire a new token.\"\n                    )\n                try:\n                    self._api_token = self._credential.get_token(\n                        \"https://cognitiveservices.azure.com/.default\"\n                    )\n                except ClientAuthenticationError as err:\n                    raise mlflow.MlflowException(\n                        \"Unable to acquire a valid Azure AD token for the resource due to \"\n                        f\"the following error: {err.message}\"\n                    ) from err\n                openai.api_key = self._api_token.token\n            if logger:\n                logger.debug(\"Token refreshed successfully\")\n        else:\n            raise mlflow.MlflowException(\n                \"OpenAI API key must be set in the ``OPENAI_API_KEY`` environment variable.\"\n            )\n", "path": "mlflow/openai/utils.py"}]}