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/Provider/nexra/NexraChatGPT.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:
```
1: from __future__ import annotations
2: 
3:+import asyncio
4: import json
5: import requests
6:+from typing import Any, Dict
7: 
-from ...typing import CreateResult, Messages
-from ..base_provider import ProviderModelMixin, AbstractProvider
8:+from ...typing import AsyncResult, Messages
9:+from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
10: from ..helper import format_prompt
11: 
-class NexraChatGPT(AbstractProvider, ProviderModelMixin):
12:+
13:+class NexraChatGPT(AsyncGeneratorProvider, ProviderModelMixin):
14:     label = "Nexra ChatGPT"
15:     url = "https://nexra.aryahcr.cc/documentation/chatgpt/en"
-    api_endpoint = "https://nexra.aryahcr.cc/api/chat/gpt"
16:+    api_endpoint_nexra_chatgpt = "https://nexra.aryahcr.cc/api/chat/gpt"
17:+    api_endpoint_nexra_chatgpt4o = "https://nexra.aryahcr.cc/api/chat/complements"
18:+    api_endpoint_nexra_chatgpt_v2 = "https://nexra.aryahcr.cc/api/chat/complements"
19:+    api_endpoint_nexra_gptweb = "https://nexra.aryahcr.cc/api/chat/gptweb"
20:     working = True
21:+    supports_system_message = True
22:+    supports_message_history = True
23:+    supports_stream = True
24:     
25:     default_model = 'gpt-3.5-turbo'
-    models = ['gpt-4', 'gpt-4-0613', 'gpt-4-0314', 'gpt-4-32k-0314', default_model, 'gpt-3.5-turbo-16k', 'gpt-3.5-turbo-0613', 'gpt-3.5-turbo-16k-0613', 'gpt-3.5-turbo-0301', 'text-davinci-003', 'text-davinci-002', 'code-davinci-002', 'gpt-3', 'text-curie-001', 'text-babbage-001', 'text-ada-001', 'davinci', 'curie', 'babbage', 'ada', 'babbage-002', 'davinci-002']
26:+    nexra_chatgpt = [
27:+        'gpt-4', 'gpt-4-0613', 'gpt-4-0314', 'gpt-4-32k-0314',
28:+        default_model, 'gpt-3.5-turbo-16k', 'gpt-3.5-turbo-0613', 'gpt-3.5-turbo-16k-0613', 'gpt-3.5-turbo-0301', 
29:+        'text-davinci-003', 'text-davinci-002', 'code-davinci-002', 'gpt-3', 'text-curie-001', 'text-babbage-001', 'text-ada-001', 'davinci', 'curie', 'babbage', 'ada', 'babbage-002', 'davinci-002'
30:+    ]
31:+    nexra_chatgpt4o = ['gpt-4o']
32:+    nexra_chatgptv2 = ['chatgpt']
33:+    nexra_gptweb = ['gptweb']
34:+    models = nexra_chatgpt + nexra_chatgpt4o + nexra_chatgptv2 + nexra_gptweb
35:     
36:     model_aliases = {
37:         "gpt-4": "gpt-4-0613",
-        "gpt-4": "gpt-4-32k",
-        "gpt-4": "gpt-4-0314",
-        "gpt-4": "gpt-4-32k-0314",
-        
38:+        "gpt-4-32k": "gpt-4-32k-0314",
39:         "gpt-3.5-turbo": "gpt-3.5-turbo-16k",
-        "gpt-3.5-turbo": "gpt-3.5-turbo-0613",
-        "gpt-3.5-turbo": "gpt-3.5-turbo-16k-0613",
-        "gpt-3.5-turbo": "gpt-3.5-turbo-0301",
-        
40:+        "gpt-3.5-turbo-0613": "gpt-3.5-turbo-16k-0613",
41:         "gpt-3": "text-davinci-003",
-        "gpt-3": "text-davinci-002",
-        "gpt-3": "code-davinci-002",
-        "gpt-3": "text-curie-001",
-        "gpt-3": "text-babbage-001",
-        "gpt-3": "text-ada-001",
-        "gpt-3": "text-ada-001",
-        "gpt-3": "davinci",
-        "gpt-3": "curie",
-        "gpt-3": "babbage",
-        "gpt-3": "ada",
-        "gpt-3": "babbage-002",
-        "gpt-3": "davinci-002",
42:+        "text-davinci-002": "code-davinci-002",
43:+        "text-curie-001": "text-babbage-001",
44:+        "text-ada-001": "davinci",
45:+        "curie": "babbage",
46:+        "ada": "babbage-002",
47:+        "davinci-002": "davinci-002",
48:+        "chatgpt": "chatgpt",
49:+        "gptweb": "gptweb"
50:     }
51: 
52:     @classmethod
57:             return cls.model_aliases[model]
58:         else:
59:             return cls.default_model
-            
60:+
61:     @classmethod
-    def create_completion(
62:+    async def create_async_generator(
63:         cls,
64:         model: str,
65:         messages: Messages,
66:+        stream: bool = False,
67:         proxy: str = None,
68:         markdown: bool = False,
69:         **kwargs
-    ) -> CreateResult:
-        model = cls.get_model(model)
70:+    ) -> AsyncResult:
71:+        if model in cls.nexra_chatgpt:
72:+            async for chunk in cls._create_async_generator_nexra_chatgpt(model, messages, proxy, **kwargs):
73:+                yield chunk
74:+        elif model in cls.nexra_chatgpt4o:
75:+            async for chunk in cls._create_async_generator_nexra_chatgpt4o(model, messages, stream, proxy, markdown, **kwargs):
76:+                yield chunk
77:+        elif model in cls.nexra_chatgptv2:
78:+            async for chunk in cls._create_async_generator_nexra_chatgpt_v2(model, messages, stream, proxy, markdown, **kwargs):
79:+                yield chunk
80:+        elif model in cls.nexra_gptweb:
81:+            async for chunk in cls._create_async_generator_nexra_gptweb(model, messages, proxy, **kwargs):
82:+                yield chunk
83: 
84:+    @classmethod
85:+    async def _create_async_generator_nexra_chatgpt(
86:+        cls,
87:+        model: str,
88:+        messages: Messages,
89:+        proxy: str = None,
90:+        markdown: bool = False,
91:+        **kwargs
92:+    ) -> AsyncResult:
93:+        model = cls.get_model(model)
94:+        
95:         headers = {
-            'Content-Type': 'application/json'
96:+            "Content-Type": "application/json"
97:         }
98:         
99:+        prompt = format_prompt(messages)
100:         data = {
-            "messages": [],
-            "prompt": format_prompt(messages),
101:+            "messages": messages,
102:+            "prompt": prompt,
103:             "model": model,
104:             "markdown": markdown
105:         }
106:+
107:+        loop = asyncio.get_event_loop()
108:+        try:
109:+            response = await loop.run_in_executor(None, cls._sync_post_request, cls.api_endpoint_nexra_chatgpt, data, headers, proxy)
110:+            filtered_response = cls._filter_response(response)
111:+            
112:+            for chunk in filtered_response:
113:+                yield chunk
114:+        except Exception as e:
115:+            print(f"Error during API request (nexra_chatgpt): {e}")
116:+
117:+    @classmethod
118:+    async def _create_async_generator_nexra_chatgpt4o(
119:+        cls,
120:+        model: str,
121:+        messages: Messages,
122:+        stream: bool = False,
123:+        proxy: str = None,
124:+        markdown: bool = False,
125:+        **kwargs
126:+    ) -> AsyncResult:
127:+        model = cls.get_model(model)
128:         
-        response = requests.post(cls.api_endpoint, headers=headers, json=data)
129:+        headers = {
130:+            "Content-Type": "application/json"
131:+        }
132:+        
133:+        prompt = format_prompt(messages)
134:+        data = {
135:+            "messages": [
136:+                {
137:+                    "role": "user",
138:+                    "content": prompt
139:+                }
140:+            ],
141:+            "stream": stream,
142:+            "markdown": markdown,
143:+            "model": model
144:+        }
145: 
-        return cls.process_response(response)
146:+        loop = asyncio.get_event_loop()
147:+        try:
148:+            response = await loop.run_in_executor(None, cls._sync_post_request, cls.api_endpoint_nexra_chatgpt4o, data, headers, proxy, stream)
149:+            
150:+            if stream:
151:+                async for chunk in cls._process_streaming_response(response):
152:+                    yield chunk
153:+            else:
154:+                for chunk in cls._process_non_streaming_response(response):
155:+                    yield chunk
156:+        except Exception as e:
157:+            print(f"Error during API request (nexra_chatgpt4o): {e}")
158: 
159:     @classmethod
-    def process_response(cls, response):
160:+    async def _create_async_generator_nexra_chatgpt_v2(
161:+        cls,
162:+        model: str,
163:+        messages: Messages,
164:+        stream: bool = False,
165:+        proxy: str = None,
166:+        markdown: bool = False,
167:+        **kwargs
168:+    ) -> AsyncResult:
169:+        model = cls.get_model(model)
170:+        
171:+        headers = {
172:+            "Content-Type": "application/json"
173:+        }
174:+        
175:+        prompt = format_prompt(messages)
176:+        data = {
177:+            "messages": [
178:+                {
179:+                    "role": "user",
180:+                    "content": prompt
181:+                }
182:+            ],
183:+            "stream": stream,
184:+            "markdown": markdown,
185:+            "model": model
186:+        }
187:+
188:+        loop = asyncio.get_event_loop()
189:+        try:
190:+            response = await loop.run_in_executor(None, cls._sync_post_request, cls.api_endpoint_nexra_chatgpt_v2, data, headers, proxy, stream)
191:+            
192:+            if stream:
193:+                async for chunk in cls._process_streaming_response(response):
194:+                    yield chunk
195:+            else:
196:+                for chunk in cls._process_non_streaming_response(response):
197:+                    yield chunk
198:+        except Exception as e:
199:+            print(f"Error during API request (nexra_chatgpt_v2): {e}")
200:+
201:+    @classmethod
202:+    async def _create_async_generator_nexra_gptweb(
203:+        cls,
204:+        model: str,
205:+        messages: Messages,
206:+        proxy: str = None,
207:+        markdown: bool = False,
208:+        **kwargs
209:+    ) -> AsyncResult:
210:+        model = cls.get_model(model)
211:+        
212:+        headers = {
213:+            "Content-Type": "application/json"
214:+        }
215:+        
216:+        prompt = format_prompt(messages)
217:+        data = {
218:+            "prompt": prompt,
219:+            "markdown": markdown,
220:+        }
221:+
222:+        loop = asyncio.get_event_loop()
223:+        try:
224:+            response = await loop.run_in_executor(None, cls._sync_post_request, cls.api_endpoint_nexra_gptweb, data, headers, proxy)
225:+            
226:+            for chunk in response.iter_content(1024):
227:+                if chunk:
228:+                    decoded_chunk = chunk.decode().lstrip('_')
229:+                    try:
230:+                        response_json = json.loads(decoded_chunk)
231:+                        if response_json.get("status"):
232:+                            yield response_json.get("gpt", "")
233:+                    except json.JSONDecodeError:
234:+                        continue
235:+        except Exception as e:
236:+            print(f"Error during API request (nexra_gptweb): {e}")
237:+
238:+    @staticmethod
239:+    def _sync_post_request(url: str, data: Dict[str, Any], headers: Dict[str, str], proxy: str = None, stream: bool = False) -> requests.Response:
240:+        proxies = {
241:+            "http": proxy,
242:+            "https": proxy,
243:+        } if proxy else None
244:+        
245:+        try:
246:+            response = requests.post(url, json=data, headers=headers, proxies=proxies, stream=stream)
247:+            response.raise_for_status()
248:+            return response
249:+        except requests.RequestException as e:
250:+            print(f"Request failed: {e}")
251:+            raise
252:+
253:+    @staticmethod
254:+    def _process_non_streaming_response(response: requests.Response) -> str:
255:         if response.status_code == 200:
256:             try:
-                data = response.json()
-                return data.get('gpt', '')
257:+                content = response.text.lstrip('')
258:+                data = json.loads(content)
259:+                return data.get('message', '')
260:             except json.JSONDecodeError:
261:                 return "Error: Unable to decode JSON response"
262:         else:
263:             return f"Error: {response.status_code}"
264:+
265:+    @staticmethod
266:+    async def _process_streaming_response(response: requests.Response):
267:+        full_message = ""
268:+        for line in response.iter_lines(decode_unicode=True):
269:+            if line:
270:+                try:
271:+                    line = line.lstrip('')
272:+                    data = json.loads(line)
273:+                    if data.get('finish'):
274:+                        break
275:+                    message = data.get('message', '')
276:+                    if message:
277:+                        yield message[len(full_message):]
278:+                        full_message = message
279:+                except json.JSONDecodeError:
280:+                    pass
281:+
282:+    @staticmethod
283:+    def _filter_response(response: requests.Response) -> str:
284:+        response_json = response.json()
285:+        return response_json.get("gpt", "")
```