import logging import asyncio import aiohttp from .ai_responder import exponential_backoff, AIResponderBase from io import BytesIO class LeonardoAIDrawMixIn(AIResponderBase): async def draw_leonardo(self, description: str) -> BytesIO: error_backoff = exponential_backoff(max_attempts=12) generation_id = None image_url = None image_bytes = None while True: error_sleep = next(error_backoff) try: async with aiohttp.ClientSession() as session: if generation_id is None: async with session.post("https://cloud.leonardo.ai/api/rest/v1/generations", json={"prompt": description, "modelId": "6bef9f1b-29cb-40c7-b9df-32b51c1f67d3", "num_images": 1, "sd_version": "v2", "promptMagic": True, "unzoomAmount": 1, "width": 512, "height": 512}, headers={"Authorization": f"Bearer {self.config['leonardo-token']}", "Accept": "application/json", "Content-Type": "application/json"}, ) as response: response = await response.json() if "sdGenerationJob" not in response: logging.warning(f"No 'sdGenerationJob' found in response, sleep for {error_sleep}s: {repr(response)}") await asyncio.sleep(error_sleep) continue generation_id = response["sdGenerationJob"]["generationId"] if image_url is None: async with session.get(f"https://cloud.leonardo.ai/api/rest/v1/generations/{generation_id}", headers={"Authorization": f"Bearer {self.config['leonardo-token']}", "Accept": "application/json"}, ) as response: response = await response.json() if "generations_by_pk" not in response: logging.warning(f"Unexpected response, sleep for {error_sleep}s: {repr(response)}") await asyncio.sleep(error_sleep) continue if len(response["generations_by_pk"]["generated_images"]) == 0: await asyncio.sleep(error_sleep) continue image_url = response["generations_by_pk"]["generated_images"][0]["url"] if image_bytes is None: async with session.get(image_url) as response: image_bytes = BytesIO(await response.read()) async with session.delete(f"https://cloud.leonardo.ai/api/rest/v1/generations/{generation_id}", headers={"Authorization": f"Bearer {self.config['leonardo-token']}"}, ) as response: await response.json() logging.info(f'Drawed a picture with leonardo AI on this description: {repr(description)}') return image_bytes except Exception as err: logging.warning(f"Failed to generate image, sleep for {error_sleep}s: {repr(description)}\n{repr(err)}") else: logging.warning(f"Failed to generate image, sleep for {error_sleep}s: {repr(description)}") await asyncio.sleep(error_sleep) raise RuntimeError(f"Failed to generate image {repr(description)}")