Your task is to review pull requests. Instructions:
- Provide the response in following JSON format: {"reviews": [{"line": <line_number>, "body": "<review comment>"}]}
- Do not give positive comments or compliments.
- Provide comments and suggestions ONLY if there is something to improve, otherwise "reviews" should be an empty array.
- Write the comment in GitHub Markdown format.
- Use the given description only for the overall context and only comment the code.
- IMPORTANT: NEVER suggest adding comments to the code.

Review the following code diff in the file "g4f/gui/server/api.py" and take the pull request title and description into account when writing the response.
  
Pull request title: [pull] main from xtekky:main
Pull request description:
---
See Commits and Changes for more details.

-----
Created by [<img src="https://prod.download/pull-18h-svg" valign="bottom"/> **pull[bot]**](https://github.com/wei/pull)

_Can you help keep this open source service alive? **[💖 Please sponsor : )](https://prod.download/pull-pr-sponsor)**_
---

Each line is prefixed by its number. Code to review:
```
2: 
3: import logging
4: import os
-import os.path
5: import uuid
6: import asyncio
7: import time
8: from aiohttp import ClientSession
-from typing import Iterator, Optional
9:+from typing import Iterator, Optional, AsyncIterator, Union
10: from flask import send_from_directory
11: 
12: from g4f import version, models
19: from g4f.providers.base_provider import ProviderModelMixin, FinishReason
20: from g4f.providers.conversation import BaseConversation
21: 
-conversations: dict[dict[str, BaseConversation]] = {}
22:+# Define the directory for generated images
23: images_dir = "./generated_images"
24: 
25:+# Function to ensure the images directory exists
26:+def ensure_images_dir():
27:+    if not os.path.exists(images_dir):
28:+        os.makedirs(images_dir)
29:+
30:+conversations: dict[dict[str, BaseConversation]] = {}
31:+
32: 
33: class Api:
34:     @staticmethod
35:     def get_models() -> list[str]:
-        """
-        Return a list of all models.
-
-        Fetches and returns a list of all available models in the system.
-
-        Returns:
-            List[str]: A list of model names.
-        """
36:         return models._all_models
37: 
38:     @staticmethod
80: 
81:     @staticmethod
82:     def get_providers() -> list[str]:
-        """
-        Return a list of all working providers.
-        """
83:         return {
84:             provider.__name__: (
85:                 provider.label if hasattr(provider, "label") else provider.__name__
94: 
95:     @staticmethod
96:     def get_version():
-        """
-        Returns the current and latest version of the application.
-
-        Returns:
-            dict: A dictionary containing the current and latest version.
-        """
97:         try:
98:             current_version = version.utils.current_version
99:         except VersionNotFoundError:
104:         }
105: 
106:     def serve_images(self, name):
107:+        ensure_images_dir()
108:         return send_from_directory(os.path.abspath(images_dir), name)
109: 
110:     def _prepare_conversation_kwargs(self, json_data: dict, kwargs: dict):
-        """
-        Prepares arguments for chat completion based on the request data.
-
-        Reads the request and prepares the necessary arguments for handling 
-        a chat completion request.
-
-        Returns:
-            dict: Arguments prepared for chat completion.
-        """
111:         model = json_data.get('model') or models.default
112:         provider = json_data.get('provider')
113:         messages = json_data['messages']
115:         if api_key is not None:
116:             kwargs["api_key"] = api_key
117:         if json_data.get('web_search'):
-            if provider in ("Bing", "HuggingChat"):
118:+            if provider:
119:                 kwargs['web_search'] = True
120:             else:
121:                 from .internet import get_search_message
140:             result = ChatCompletion.create(**kwargs)
141:             first = True
142:             if isinstance(result, ImageResponse):
-                # Якщо результат є ImageResponse, обробляємо його як одиночний елемент
143:                 if first:
144:                     first = False
145:                     yield self._format_json("provider", get_last_provider(True))
146:                 yield self._format_json("content", str(result))
147:             else:
-                # Якщо результат є ітерабельним, обробляємо його як раніше
148:                 for chunk in result:
149:                     if first:
150:                         first = False
160:                     elif isinstance(chunk, ImagePreview):
161:                         yield self._format_json("preview", chunk.to_string())
162:                     elif isinstance(chunk, ImageResponse):
-                        # Обробка ImageResponse
163:                         images = asyncio.run(self._copy_images(chunk.get_list(), chunk.options.get("cookies")))
164:                         yield self._format_json("content", str(ImageResponse(images, chunk.alt)))
165:                     elif not isinstance(chunk, FinishReason):
168:             logging.exception(e)
169:             yield self._format_json('error', get_error_message(e))
170: 
-    # Додайте цей метод до класу Api
171:     async def _copy_images(self, images: list[str], cookies: Optional[Cookies] = None):
172:+        ensure_images_dir()
173:         async with ClientSession(
174:             connector=get_connector(None, os.environ.get("G4F_PROXY")),
175:             cookies=cookies
190:             return await asyncio.gather(*[copy_image(image) for image in images])
191: 
192:     def _format_json(self, response_type: str, content):
-        """
-        Formats and returns a JSON response.
-
-        Args:
-            response_type (str): The type of the response.
-            content: The content to be included in the response.
-
-        Returns:
-            str: A JSON formatted string.
-        """
193:         return {
194:             'type': response_type,
195:             response_type: content
197: 
198: 
199: def get_error_message(exception: Exception) -> str:
-    """
-    Generates a formatted error message from an exception.
-
-    Args:
-        exception (Exception): The exception to format.
-
-    Returns:
-        str: A formatted error message string.
-    """
200:     message = f"{type(exception).__name__}: {exception}"
201:     provider = get_last_provider()
202:     if provider is None:
```