GPTRouter 0.3.2__tar.gz → 0.3.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: GPTRouter
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: A Python package for working with GPTRouter APIs
5
5
  Author-email: sirjanpreet@writesonic.com
6
6
  Classifier: Development Status :: 3 - Alpha
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: GPTRouter
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: A Python package for working with GPTRouter APIs
5
5
  Author-email: sirjanpreet@writesonic.com
6
6
  Classifier: Development Status :: 3 - Alpha
@@ -0,0 +1,383 @@
1
+ from __future__ import annotations
2
+ from pydantic import parse_obj_as
3
+ import logging
4
+ import json
5
+ import httpx
6
+ from typing import Generator, List, Optional, Union
7
+
8
+ from gpt_router.models import (
9
+ GPTRouterMetadata,
10
+ ImageGenerationRequest,
11
+ ImageGenerationResponse,
12
+ ModelGenerationRequest,
13
+ GenerationResponse,
14
+ ChunkedGenerationResponse,
15
+ )
16
+ from gpt_router.exceptions import (
17
+ GPTRouterApiTimeoutError,
18
+ GPTRouterBadRequestError,
19
+ GPTRouterStreamingError,
20
+ GPTRouterForbiddenError,
21
+ GPTRouterInternalServerError,
22
+ GPTRouterNotAvailableError,
23
+ GPTRouterTooManyRequestsError,
24
+ GPTRouterUnauthorizedError,
25
+ )
26
+ from gpt_router.constants import DEFAULT_REQUEST_TIMEOUT
27
+
28
+ from tenacity import (
29
+ Retrying,
30
+ AsyncRetrying,
31
+ retry_if_exception_type,
32
+ stop_after_attempt,
33
+ wait_fixed,
34
+ )
35
+
36
+ logger = logging.getLogger(__name__)
37
+
38
+ STATUS_CODE_EXCEPTION_MAPPING = {
39
+ 400: GPTRouterBadRequestError,
40
+ 406: GPTRouterNotAvailableError,
41
+ 401: GPTRouterUnauthorizedError,
42
+ 403: GPTRouterForbiddenError,
43
+ 429: GPTRouterTooManyRequestsError,
44
+ 500: GPTRouterInternalServerError,
45
+ 503: GPTRouterNotAvailableError,
46
+ }
47
+
48
+
49
+ class ServerError(Exception):
50
+ pass
51
+
52
+
53
+ class GPTRouterClient:
54
+ models = None
55
+ request_timeout = DEFAULT_REQUEST_TIMEOUT
56
+
57
+ def __init__(
58
+ self,
59
+ base_url,
60
+ api_key,
61
+ request_timeout: int = 60,
62
+ stream_read_timeout: Optional[int] = None,
63
+ additional_metadata: Optional[GPTRouterMetadata] = None,
64
+ ):
65
+ self.base_url = base_url
66
+ self.api_key = api_key
67
+ self.request_timeout = request_timeout
68
+ self.additional_metadata = additional_metadata
69
+ self.stream_read_timeout = (
70
+ request_timeout if stream_read_timeout is None else stream_read_timeout
71
+ )
72
+
73
+ def add_metadata_info(
74
+ self,
75
+ payload: dict,
76
+ model_router_metadata: Optional[GPTRouterMetadata] = None,
77
+ ):
78
+ metadata = {}
79
+ if self.additional_metadata:
80
+ metadata.update(self.additional_metadata.dict())
81
+ if model_router_metadata:
82
+ metadata.update(model_router_metadata.dict())
83
+
84
+ payload.update(
85
+ {
86
+ "metadata": metadata,
87
+ "tag": metadata.get("tag"),
88
+ "createdByUserId": metadata.get("created_by_user_id"),
89
+ "historyId": (
90
+ str(metadata["history_id"]) if metadata.get("history_id") else None
91
+ ),
92
+ }
93
+ )
94
+
95
+ payload = {k: v for k, v in payload.items() if v is not None}
96
+ return payload
97
+
98
+ async def _async_api_call(self, *, path: str, method: str, payload: dict):
99
+ try:
100
+ async with httpx.AsyncClient() as client:
101
+ response = await client.request(
102
+ method,
103
+ url=self.base_url.rstrip("/")
104
+ + ("/api" if not self.base_url.endswith("/api") else "")
105
+ + path,
106
+ headers={
107
+ "content-type": "application/json",
108
+ "ws-secret": self.api_key,
109
+ },
110
+ json=payload,
111
+ timeout=self.request_timeout,
112
+ )
113
+ if response.status_code == 200:
114
+ return response.json()
115
+ elif response.status_code == 202 or response.status_code == 204:
116
+ return None
117
+ else:
118
+ error_class = STATUS_CODE_EXCEPTION_MAPPING.get(
119
+ response.status_code, Exception
120
+ )
121
+ raise error_class(response.json())
122
+ except httpx.TimeoutException as err:
123
+ logger.error(f"Timeout error: {err}")
124
+ raise GPTRouterApiTimeoutError("Api Request timed out")
125
+
126
+ def _api_call(self, *, path: str, method: str, payload: dict):
127
+ try:
128
+ with httpx.Client() as client:
129
+ response = client.request(
130
+ method,
131
+ url=self.base_url.rstrip("/")
132
+ + ("/api" if not self.base_url.endswith("/api") else "")
133
+ + path,
134
+ headers={
135
+ "content-type": "application/json",
136
+ "ws-secret": self.api_key,
137
+ },
138
+ json=payload,
139
+ timeout=self.request_timeout,
140
+ )
141
+ if response.status_code == 200:
142
+ return response.json()
143
+ elif response.status_code == 202 or response.status_code == 204:
144
+ return None
145
+ else:
146
+ error_class = STATUS_CODE_EXCEPTION_MAPPING.get(
147
+ response.status_code, Exception
148
+ )
149
+ raise error_class(response.json())
150
+ except httpx.TimeoutException as err:
151
+ logger.error(f"Timeout error: {err}")
152
+ raise GPTRouterApiTimeoutError("Api Request timed out")
153
+
154
+ async def astream_events(
155
+ self, *, path: str, method: str, payload: dict, retry_count: int = 1
156
+ ):
157
+ async_retrying = AsyncRetrying(
158
+ stop=stop_after_attempt(retry_count),
159
+ wait=wait_fixed(0.5),
160
+ retry=(
161
+ retry_if_exception_type(httpx.ReadTimeout)
162
+ | retry_if_exception_type(ServerError)
163
+ | retry_if_exception_type(httpx.ReadError)
164
+ ),
165
+ before_sleep=lambda retry_state: logger.warn(
166
+ f"Read timeout. Retrying... (Attempt {retry_state.attempt_number} of {retry_count})"
167
+ ),
168
+ )
169
+ attempt_number = 0
170
+ async for attempt in async_retrying:
171
+ attempt_number += 1
172
+
173
+ if attempt_number < retry_count:
174
+ read_timeout = self.stream_read_timeout
175
+ else:
176
+ read_timeout = self.request_timeout
177
+ try:
178
+ async with httpx.AsyncClient() as client:
179
+ async with client.stream(
180
+ method,
181
+ url=self.base_url.rstrip("/")
182
+ + ("/api" if not self.base_url.endswith("/api") else "")
183
+ + path,
184
+ data=json.dumps(payload),
185
+ headers={
186
+ "Content-type": "application/json",
187
+ "ws-secret": self.api_key,
188
+ },
189
+ timeout=httpx.Timeout(self.request_timeout, read=read_timeout),
190
+ ) as response:
191
+ if response.status_code >= 500:
192
+ raise ServerError("Server error")
193
+ response.raise_for_status()
194
+ async for line in response.aiter_lines():
195
+ try:
196
+ if line.strip() == "":
197
+ continue
198
+
199
+ line_type, line_data = (
200
+ segment.strip() for segment in line.split(":", 1)
201
+ )
202
+
203
+ if line_type != "data":
204
+ continue
205
+
206
+ data: dict = json.loads(line_data.strip())
207
+ if data["event"] == "error":
208
+ raise GPTRouterStreamingError(data)
209
+ yield parse_obj_as(ChunkedGenerationResponse, data)
210
+ except GPTRouterStreamingError as e:
211
+ raise e
212
+ except Exception:
213
+ continue
214
+
215
+ return
216
+ except (httpx.ReadTimeout, ServerError, httpx.ReadError) as err:
217
+ logger.error(str(err))
218
+ if attempt_number == retry_count:
219
+ logger.error("All retry attempts failed")
220
+ raise
221
+ except httpx.HTTPStatusError as err:
222
+ raise Exception(
223
+ f"HTTP Error {err.response.status_code}: {err.response.text}"
224
+ ) from err
225
+ except httpx.TimeoutException as err:
226
+ raise TimeoutError("Request timed out") from err
227
+
228
+ def stream_events(
229
+ self, *, path: str, method: str, payload: dict, retry_count: int = 1
230
+ ) -> Generator[ChunkedGenerationResponse]:
231
+ retrying = Retrying(
232
+ stop=stop_after_attempt(retry_count),
233
+ wait=wait_fixed(0.5),
234
+ retry=(
235
+ retry_if_exception_type(httpx.ReadTimeout)
236
+ | retry_if_exception_type(ServerError)
237
+ | retry_if_exception_type(httpx.ReadError)
238
+ ),
239
+ before_sleep=lambda retry_state: logger.warn(
240
+ f"Read timeout. Retrying... (Attempt {retry_state.attempt_number} of {retry_count})"
241
+ ),
242
+ )
243
+
244
+ attempt_number = 0
245
+ for attempt in retrying:
246
+ attempt_number += 1
247
+
248
+ if attempt_number < retry_count:
249
+ read_timeout = self.stream_read_timeout
250
+ else:
251
+ read_timeout = self.request_timeout
252
+
253
+ try:
254
+ with httpx.Client() as client:
255
+ with client.stream(
256
+ method=method,
257
+ url=self.base_url.rstrip("/")
258
+ + ("/api" if not self.base_url.endswith("/api") else "")
259
+ + path,
260
+ data=json.dumps(payload),
261
+ headers={
262
+ "Content-type": "application/json",
263
+ "ws-secret": self.api_key,
264
+ },
265
+ timeout=httpx.Timeout(self.request_timeout, read=read_timeout),
266
+ ) as response:
267
+ if response.status_code >= 500:
268
+ raise ServerError("Server error")
269
+ response.raise_for_status()
270
+ for line in response.iter_lines():
271
+ try:
272
+ if line.strip() == "":
273
+ continue
274
+
275
+ line_type, line_data = (
276
+ segment.strip() for segment in line.split(":", 1)
277
+ )
278
+ if line_type != "data":
279
+ continue
280
+
281
+ data = json.loads(line_data.strip())
282
+ if data["event"].lower() == "error":
283
+ raise GPTRouterStreamingError(data["message"])
284
+ yield parse_obj_as(ChunkedGenerationResponse, data)
285
+ except GPTRouterStreamingError as e:
286
+ raise e
287
+ except Exception:
288
+ continue
289
+ return
290
+ except (httpx.ReadTimeout, ServerError, httpx.ReadError) as err:
291
+ logger.error(str(err))
292
+ if attempt_number == retry_count:
293
+ logger.error("All retry attempts failed")
294
+ raise
295
+ except httpx.HTTPStatusError as err:
296
+ raise Exception(
297
+ f"HTTP Error {err.response.status_code}: {err.response.text}"
298
+ ) from err
299
+ except httpx.TimeoutException as err:
300
+ raise TimeoutError("Request timed out") from err
301
+
302
+ def generate(
303
+ self,
304
+ *,
305
+ ordered_generation_requests: List[ModelGenerationRequest],
306
+ is_stream=False,
307
+ model_router_metadata: Optional[GPTRouterMetadata] = None,
308
+ **kwargs,
309
+ ) -> Union[GenerationResponse, Generator[ChunkedGenerationResponse]]:
310
+ api_path = "/v1/generate"
311
+ api_method = "POST"
312
+ api_payload = {
313
+ "stream": is_stream,
314
+ "data": [
315
+ request.dict(exclude_none=True, by_alias=True)
316
+ for request in ordered_generation_requests
317
+ ],
318
+ }
319
+ api_payload = self.add_metadata_info(api_payload, model_router_metadata)
320
+ if is_stream:
321
+ return self.stream_events(
322
+ path=api_path,
323
+ method=api_method,
324
+ payload=api_payload,
325
+ )
326
+ result = self._api_call(
327
+ path=api_path,
328
+ method=api_method,
329
+ payload=api_payload,
330
+ )
331
+ return parse_obj_as(GenerationResponse, result)
332
+
333
+ async def agenerate(
334
+ self,
335
+ *,
336
+ ordered_generation_requests: List[ModelGenerationRequest],
337
+ is_stream=False,
338
+ model_router_metadata: Optional[GPTRouterMetadata] = None,
339
+ **kwargs,
340
+ ) -> GenerationResponse:
341
+ api_path = "/v1/generate"
342
+ api_method = "POST"
343
+ api_payload = {
344
+ "stream": is_stream,
345
+ "data": [
346
+ request.dict(exclude_none=True, by_alias=True)
347
+ for request in ordered_generation_requests
348
+ ],
349
+ }
350
+ api_payload = self.add_metadata_info(api_payload, model_router_metadata)
351
+ if is_stream:
352
+ return self.astream_events(
353
+ path=api_path,
354
+ method=api_method,
355
+ payload=api_payload,
356
+ )
357
+ result = await self._async_api_call(
358
+ path=api_path,
359
+ method=api_method,
360
+ payload=api_payload,
361
+ )
362
+ return parse_obj_as(GenerationResponse, result)
363
+
364
+ async def agenerate_images(
365
+ self, *, image_generation_request: ImageGenerationRequest
366
+ ) -> List[ImageGenerationResponse]:
367
+ api_path = "/v1/generate/generate-image"
368
+ api_method = "POST"
369
+ api_payload = image_generation_request.dict()
370
+
371
+ api_response = await self._async_api_call(
372
+ path=api_path,
373
+ method=api_method,
374
+ payload=api_payload,
375
+ )
376
+ generated_images = api_response.get("response", [])
377
+ if isinstance(generated_images, dict):
378
+ generated_images = generated_images.get("artifacts", [])
379
+
380
+ return [
381
+ parse_obj_as(ImageGenerationResponse, generated_img)
382
+ for generated_img in generated_images
383
+ ]
@@ -33,6 +33,7 @@ class GenerationParams(BaseModel):
33
33
  user_id: Optional[str] = None
34
34
  history_id: Optional[str] = None
35
35
  metadata: Optional[dict] = None
36
+ raw_event: Optional[bool] = None
36
37
 
37
38
 
38
39
  class ModelGenerationRequest(BaseModel):
@@ -78,6 +79,7 @@ class GenerationResponse(BaseModel):
78
79
  class ChunkedGenerationResponse(BaseModel):
79
80
  event: str
80
81
  data: dict
82
+ provider: Optional[str] = None
81
83
 
82
84
 
83
85
  class ImageGenerationRequest(BaseModel):
@@ -11,6 +11,7 @@ httpx = "^0.25.2"
11
11
  pydantic = "^1.10.14"
12
12
  pyhumps = "^3.8.0"
13
13
  python-dotenv = "^1.0.0"
14
+ tenacity = "^9.0.0"
14
15
 
15
16
 
16
17
  [build-system]
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setup(
7
7
  name="GPTRouter",
8
- version="0.3.2",
8
+ version="0.3.4",
9
9
  description="A Python package for working with GPTRouter APIs",
10
10
  long_description=long_description,
11
11
  long_description_content_type="text/markdown",
@@ -1,282 +0,0 @@
1
- from __future__ import annotations
2
- from pydantic import parse_obj_as
3
- import logging
4
- import json
5
- import httpx
6
- from typing import Generator, List, Optional, Union
7
-
8
- from gpt_router.models import (
9
- GPTRouterMetadata,
10
- ImageGenerationRequest,
11
- ImageGenerationResponse,
12
- ModelGenerationRequest,
13
- GenerationResponse,
14
- ChunkedGenerationResponse,
15
- )
16
- from gpt_router.exceptions import (
17
- GPTRouterApiTimeoutError,
18
- GPTRouterBadRequestError,
19
- GPTRouterStreamingError,
20
- GPTRouterForbiddenError,
21
- GPTRouterInternalServerError,
22
- GPTRouterNotAvailableError,
23
- GPTRouterTooManyRequestsError,
24
- GPTRouterUnauthorizedError,
25
- )
26
- from gpt_router.constants import DEFAULT_REQUEST_TIMEOUT
27
-
28
- logger = logging.getLogger(__name__)
29
-
30
- STATUS_CODE_EXCEPTION_MAPPING = {
31
- 400: GPTRouterBadRequestError,
32
- 406: GPTRouterNotAvailableError,
33
- 401: GPTRouterUnauthorizedError,
34
- 403: GPTRouterForbiddenError,
35
- 429: GPTRouterTooManyRequestsError,
36
- 500: GPTRouterInternalServerError,
37
- 503: GPTRouterNotAvailableError,
38
- }
39
-
40
-
41
- class GPTRouterClient:
42
- models = None
43
- request_timeout = DEFAULT_REQUEST_TIMEOUT
44
-
45
- def __init__(self, base_url, api_key, request_timeout: int = 60, additional_metadata: Optional[GPTRouterMetadata] = None):
46
- self.base_url = base_url
47
- self.api_key = api_key
48
- self.request_timeout = request_timeout
49
- self.additional_metadata = additional_metadata
50
-
51
- def add_metadata_info(
52
- self,
53
- payload: dict,
54
- model_router_metadata: Optional[GPTRouterMetadata] = None,
55
- ):
56
- metadata = {}
57
- if self.additional_metadata:
58
- metadata.update(self.additional_metadata.dict())
59
- if model_router_metadata:
60
- metadata.update(model_router_metadata.dict())
61
-
62
- payload.update(
63
- {
64
- "metadata": metadata,
65
- "tag": metadata.get('tag'),
66
- "createdByUserId": metadata['created_by_user_id'],
67
- "historyId": str(metadata['history_id']) if metadata.get('history_id') else None,
68
- }
69
- )
70
-
71
- payload = {k: v for k, v in payload.items() if v is not None}
72
- return payload
73
-
74
- async def _async_api_call(self, *, path: str, method: str, payload: dict):
75
- try:
76
- async with httpx.AsyncClient() as client:
77
- response = await client.request(
78
- method,
79
- url=self.base_url.rstrip('/') + ('/api' if not self.base_url.endswith('/api') else '') + path,
80
- headers={
81
- "content-type": "application/json",
82
- "ws-secret": self.api_key,
83
- },
84
- json=payload,
85
- timeout=self.request_timeout,
86
- )
87
- if response.status_code == 200:
88
- return response.json()
89
- elif response.status_code == 202 or response.status_code == 204:
90
- return None
91
- else:
92
- error_class = STATUS_CODE_EXCEPTION_MAPPING.get(
93
- response.status_code, Exception
94
- )
95
- raise error_class(response.json())
96
- except httpx.TimeoutException as err:
97
- logger.error(f"Timeout error: {err}")
98
- raise GPTRouterApiTimeoutError("Api Request timed out")
99
-
100
- def _api_call(self, *, path: str, method: str, payload: dict):
101
- try:
102
- with httpx.Client() as client:
103
- response = client.request(
104
- method,
105
- url=self.base_url.rstrip('/') + ('/api' if not self.base_url.endswith('/api') else '') + path,
106
- headers={
107
- "content-type": "application/json",
108
- "ws-secret": self.api_key,
109
- },
110
- json=payload,
111
- timeout=self.request_timeout,
112
- )
113
- if response.status_code == 200:
114
- return response.json()
115
- elif response.status_code == 202 or response.status_code == 204:
116
- return None
117
- else:
118
- error_class = STATUS_CODE_EXCEPTION_MAPPING.get(
119
- response.status_code, Exception
120
- )
121
- raise error_class(response.json())
122
- except httpx.TimeoutException as err:
123
- logger.error(f"Timeout error: {err}")
124
- raise GPTRouterApiTimeoutError("Api Request timed out")
125
-
126
- async def astream_events(self, *, path: str, method: str, payload: dict):
127
- try:
128
- async with httpx.AsyncClient() as client:
129
- async with client.stream(
130
- method,
131
- url=self.base_url.rstrip('/') + ('/api' if not self.base_url.endswith('/api') else '') + path,
132
- data=json.dumps(payload),
133
- headers={
134
- "Content-type": "application/json",
135
- "ws-secret": self.api_key,
136
- },
137
- timeout=self.request_timeout,
138
- ) as response:
139
- async for line in response.aiter_lines():
140
- try:
141
- if line.strip() == "":
142
- continue
143
-
144
- line_type, line_data = (
145
- segment.strip() for segment in line.split(":", 1)
146
- )
147
-
148
- if line_type != "data":
149
- continue
150
-
151
- data: dict = json.loads(line_data.strip())
152
- if data["event"] == "error":
153
- raise GPTRouterStreamingError(data)
154
- yield parse_obj_as(ChunkedGenerationResponse, data)
155
- except GPTRouterStreamingError as e:
156
- raise e
157
- except Exception:
158
- continue
159
- except httpx.TimeoutException as err:
160
- logger.error(f"Timeout error: {err}")
161
- raise TimeoutError("Request timed out")
162
-
163
- def stream_events(
164
- self, *, path: str, method: str, payload: dict
165
- ) -> Generator[ChunkedGenerationResponse]:
166
- try:
167
- with httpx.Client() as client:
168
- with client.stream(
169
- method=method,
170
- url=self.base_url.rstrip('/') + ('/api' if not self.base_url.endswith('/api') else '') + path,
171
- data=json.dumps(payload),
172
- headers={
173
- "Content-type": "application/json",
174
- "ws-secret": self.api_key,
175
- },
176
- timeout=self.request_timeout,
177
- ) as response:
178
- for line in response.iter_lines():
179
- try:
180
- if line.strip() == "":
181
- continue
182
-
183
- line_type, line_data = (
184
- segment.strip() for segment in line.split(":", 1)
185
- )
186
- if line_type != "data":
187
- continue
188
-
189
- data = json.loads(line_data.strip())
190
- if data["event"].lower() == "error":
191
- raise GPTRouterStreamingError(data["message"])
192
- yield parse_obj_as(ChunkedGenerationResponse, data)
193
- except GPTRouterStreamingError as e:
194
- raise e
195
- except Exception:
196
- continue
197
- except httpx.TimeoutException as err:
198
- logger.error(f"Timeout error: {err}")
199
- raise TimeoutError("Request timed out")
200
-
201
- def generate(
202
- self,
203
- *,
204
- ordered_generation_requests: List[ModelGenerationRequest],
205
- is_stream=False,
206
- model_router_metadata: Optional[GPTRouterMetadata] = None,
207
- **kwargs,
208
- ) -> Union[GenerationResponse, Generator[ChunkedGenerationResponse]]:
209
- api_path = "/v1/generate"
210
- api_method = "POST"
211
- api_payload = {
212
- "stream": is_stream,
213
- "data": [
214
- request.dict(exclude_none=True, by_alias=True)
215
- for request in ordered_generation_requests
216
- ],
217
- }
218
- api_payload = self.add_metadata_info(api_payload, model_router_metadata)
219
- if is_stream:
220
- return self.stream_events(
221
- path=api_path,
222
- method=api_method,
223
- payload=api_payload,
224
- )
225
- result = self._api_call(
226
- path=api_path,
227
- method=api_method,
228
- payload=api_payload,
229
- )
230
- return parse_obj_as(GenerationResponse, result)
231
-
232
- async def agenerate(
233
- self,
234
- *,
235
- ordered_generation_requests: List[ModelGenerationRequest],
236
- is_stream=False,
237
- model_router_metadata: Optional[GPTRouterMetadata] = None,
238
- **kwargs,
239
- ) -> GenerationResponse:
240
- api_path = "/v1/generate"
241
- api_method = "POST"
242
- api_payload = {
243
- "stream": is_stream,
244
- "data": [
245
- request.dict(exclude_none=True, by_alias=True)
246
- for request in ordered_generation_requests
247
- ],
248
- }
249
- api_payload = self.add_metadata_info(api_payload, model_router_metadata)
250
- if is_stream:
251
- return self.astream_events(
252
- path=api_path,
253
- method=api_method,
254
- payload=api_payload,
255
- )
256
- result = await self._async_api_call(
257
- path=api_path,
258
- method=api_method,
259
- payload=api_payload,
260
- )
261
- return parse_obj_as(GenerationResponse, result)
262
-
263
- async def agenerate_images(
264
- self, *, image_generation_request: ImageGenerationRequest
265
- ) -> List[ImageGenerationResponse]:
266
- api_path = "/v1/generate/generate-image"
267
- api_method = "POST"
268
- api_payload = image_generation_request.dict()
269
-
270
- api_response = await self._async_api_call(
271
- path=api_path,
272
- method=api_method,
273
- payload=api_payload,
274
- )
275
- generated_images = api_response.get("response", [])
276
- if isinstance(generated_images, dict):
277
- generated_images = generated_images.get("artifacts", [])
278
-
279
- return [
280
- parse_obj_as(ImageGenerationResponse, generated_img)
281
- for generated_img in generated_images
282
- ]
File without changes
File without changes
File without changes
File without changes