feat: support async images (#57)
This commit is contained in:
parent
6d9d9f84a4
commit
55646149ff
4 changed files with 195 additions and 2 deletions
99
examples/async_image_generator.py
Normal file
99
examples/async_image_generator.py
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
import asyncio
|
||||||
|
import time
|
||||||
|
|
||||||
|
from zai import ZaiClient
|
||||||
|
|
||||||
|
|
||||||
|
class AsyncImageGenerator:
|
||||||
|
def __init__(self):
|
||||||
|
self.client = ZaiClient()
|
||||||
|
|
||||||
|
async def generate_image(
|
||||||
|
self,
|
||||||
|
prompt: str,
|
||||||
|
model: str = 'glm-image',
|
||||||
|
size: str = None,
|
||||||
|
quality: str = None,
|
||||||
|
max_wait_time: int = 300,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Asynchronous image generation method
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prompt: Image generation prompt
|
||||||
|
model: Model to use for image generation
|
||||||
|
size: Size of the generated image
|
||||||
|
quality: Quality level of the generated image
|
||||||
|
max_wait_time: Maximum wait time (seconds)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Image generation result
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Submit generation task
|
||||||
|
print('Submitting image generation task...')
|
||||||
|
response = self.client.images.async_generations(
|
||||||
|
model=model,
|
||||||
|
prompt=prompt,
|
||||||
|
size=size,
|
||||||
|
quality=quality,
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f'Task submitted successfully, Task ID: {response.id}')
|
||||||
|
print(f'Initial response: {response}')
|
||||||
|
|
||||||
|
# Asynchronously wait for task completion
|
||||||
|
task_id = response.id
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# Check for timeout
|
||||||
|
if time.time() - start_time > max_wait_time:
|
||||||
|
raise TimeoutError(f'Image generation timeout, exceeded {max_wait_time} seconds')
|
||||||
|
|
||||||
|
# Get task result
|
||||||
|
print(f'Querying task status... (waited {int(time.time() - start_time)} seconds)')
|
||||||
|
result = self.client.images.retrieve_images_result(id=task_id)
|
||||||
|
|
||||||
|
print(f'Task status: {result.task_status}')
|
||||||
|
|
||||||
|
# Check if task is completed
|
||||||
|
if result.task_status == 'SUCCESS':
|
||||||
|
print('Image generation completed!')
|
||||||
|
return result
|
||||||
|
elif result.task_status == 'FAIL':
|
||||||
|
raise Exception(f'Image generation failed: {result}')
|
||||||
|
elif result.task_status in ['PROCESSING']:
|
||||||
|
print(f'Task in progress, status: {result.task_status}')
|
||||||
|
else:
|
||||||
|
print(f'Unknown status: {result.task_status}')
|
||||||
|
|
||||||
|
# Wait 3 seconds before querying again
|
||||||
|
await asyncio.sleep(30)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Error occurred during image generation: {e}')
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
# Usage example
|
||||||
|
async def main():
|
||||||
|
generator = AsyncImageGenerator()
|
||||||
|
try:
|
||||||
|
result = await generator.generate_image(
|
||||||
|
prompt='A beautiful sunset over the ocean with colorful clouds',
|
||||||
|
model='glm-image',
|
||||||
|
)
|
||||||
|
print('\n=== Final Result ===')
|
||||||
|
print(f'Task Status: {result.task_status}')
|
||||||
|
print(f'Request ID: {result.request_id}')
|
||||||
|
if result.image_result:
|
||||||
|
for i, img in enumerate(result.image_result):
|
||||||
|
print(f'Image {i + 1} URL: {img.url}')
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Generation failed: {e}')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
asyncio.run(main())
|
||||||
|
|
@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Optional
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from zai.core import NOT_GIVEN, BaseAPI, Body, Headers, NotGiven, make_request_options
|
from zai.core import NOT_GIVEN, BaseAPI, Body, Headers, NotGiven, make_request_options
|
||||||
from zai.types.image import ImagesResponded
|
from zai.types.image import AsyncImagesResponded, ImagesResponded
|
||||||
from zai.types.sensitive_word_check import SensitiveWordCheckRequest
|
from zai.types.sensitive_word_check import SensitiveWordCheckRequest
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|
@ -84,3 +84,75 @@ class Images(BaseAPI):
|
||||||
cast_type=_cast_type,
|
cast_type=_cast_type,
|
||||||
stream=False,
|
stream=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def async_generations(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
prompt: str,
|
||||||
|
model: str | NotGiven = NOT_GIVEN,
|
||||||
|
quality: Optional[str] | NotGiven = NOT_GIVEN,
|
||||||
|
size: Optional[str] | NotGiven = NOT_GIVEN,
|
||||||
|
request_id: Optional[str] | NotGiven = NOT_GIVEN,
|
||||||
|
user_id: Optional[str] | NotGiven = NOT_GIVEN,
|
||||||
|
extra_headers: Headers | None = None,
|
||||||
|
extra_body: Body | None = None,
|
||||||
|
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
|
||||||
|
watermark_enabled: Optional[bool] | NotGiven = NOT_GIVEN,
|
||||||
|
) -> AsyncImagesResponded:
|
||||||
|
"""
|
||||||
|
Asynchronously generate images from text prompts. Only support glm-image model
|
||||||
|
Use retrieve_images_result() to poll for the result.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
prompt (str): Text description of the desired image
|
||||||
|
model (str): The model to use for image generation
|
||||||
|
quality (Optional[str]): Quality level of the generated images
|
||||||
|
size (Optional[str]): Size of the generated images
|
||||||
|
request_id (Optional[str]): Unique identifier for the request
|
||||||
|
user_id (Optional[str]): User identifier
|
||||||
|
extra_headers (Headers): Additional headers to send
|
||||||
|
extra_body (Body): Additional body parameters
|
||||||
|
timeout (float | httpx.Timeout): Request timeout
|
||||||
|
watermark_enabled (Optional[bool]): Whether to enable watermark on generated images
|
||||||
|
"""
|
||||||
|
return self._post(
|
||||||
|
'/async/images/generations',
|
||||||
|
body={
|
||||||
|
'prompt': prompt,
|
||||||
|
'model': model,
|
||||||
|
'quality': quality,
|
||||||
|
'size': size,
|
||||||
|
'user_id': user_id,
|
||||||
|
'request_id': request_id,
|
||||||
|
'watermark_enabled': watermark_enabled,
|
||||||
|
},
|
||||||
|
options=make_request_options(extra_headers=extra_headers, extra_body=extra_body, timeout=timeout),
|
||||||
|
cast_type=AsyncImagesResponded,
|
||||||
|
stream=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def retrieve_images_result(
|
||||||
|
self,
|
||||||
|
id: str,
|
||||||
|
*,
|
||||||
|
extra_headers: Headers | None = None,
|
||||||
|
extra_body: Body | None = None,
|
||||||
|
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
|
||||||
|
) -> AsyncImagesResponded:
|
||||||
|
"""
|
||||||
|
Retrieve the result of an async image generation operation
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
id (str): Unique identifier for the image generation task
|
||||||
|
extra_headers (Headers): Additional headers to send
|
||||||
|
extra_body (Body): Additional body parameters
|
||||||
|
timeout (float | httpx.Timeout): Request timeout
|
||||||
|
"""
|
||||||
|
if not id:
|
||||||
|
raise ValueError('`id` must be provided.')
|
||||||
|
|
||||||
|
return self._get(
|
||||||
|
f'/async-result/{id}',
|
||||||
|
options=make_request_options(extra_headers=extra_headers, extra_body=extra_body, timeout=timeout),
|
||||||
|
cast_type=AsyncImagesResponded,
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from .image import GeneratedImage, ImagesResponded
|
from .image import AsyncImagesResponded, GeneratedImage, ImagesResponded
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'GeneratedImage',
|
'GeneratedImage',
|
||||||
'ImagesResponded',
|
'ImagesResponded',
|
||||||
|
'AsyncImagesResponded',
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -31,3 +31,24 @@ class ImagesResponded(BaseModel):
|
||||||
|
|
||||||
created: int
|
created: int
|
||||||
data: List[GeneratedImage]
|
data: List[GeneratedImage]
|
||||||
|
|
||||||
|
|
||||||
|
class AsyncImagesResponded(BaseModel):
|
||||||
|
"""
|
||||||
|
Async image generation response
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
id (Optional[str]): The task order number generated by the Z.ai open platform.
|
||||||
|
Please use this order number when calling the request result interface.
|
||||||
|
model (str): Model name
|
||||||
|
request_id (str): The task number submitted by the user when requesting on the client
|
||||||
|
or the task number generated by the platform.
|
||||||
|
task_status (str): Processing status, PROCESSING (processing), SUCCESS (successful), FAIL (failed).
|
||||||
|
image_result (Optional[List[GeneratedImage]]): Image generation result, available when task_status is SUCCESS
|
||||||
|
"""
|
||||||
|
|
||||||
|
id: Optional[str] = None
|
||||||
|
model: str
|
||||||
|
request_id: str
|
||||||
|
task_status: str
|
||||||
|
image_result: Optional[List[GeneratedImage]] = None
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue