leonardo#
__all__ = ['LeonardoImageGenerationDriver']module-attribute
Bases: BaseImageGenerationDriver “)
Attributes#
Name |
Type |
Description |
|---|---|---|
<a href="base_image_generation_driver.mdx#griptape.drivers.image_generation.base_image_generation_driver.BaseImageGenerationDriver.model" title="model = field(kw_only=True, metadata={'serializable': True}) class-attribute instance-attribute (griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.model)"><code class="language-python">model</code></a> |
str |
The ID of the model to use when generating images.<br/> |
<a href="leonardo.mdx#griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.api_key" title="api_key = field(kw_only=True, metadata={'serializable': True}) class-attribute instance-attribute (griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.api_key)"><code class="language-python">api_key</code></a> |
str |
The API key to use when making requests to the Leonardo API.<br/> |
<a href="leonardo.mdx#griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.requests_session" title="requests_session = field(default=Factory(lambda: requests.Session()), kw_only=True) class-attribute instance-attribute (griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.requests_session)"><code class="language-python">requests_session</code></a> |
Session |
The requests session to use when making requests to the Leonardo API.<br/> |
<a href="leonardo.mdx#griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.api_base" title="api_base = 'https://cloud.leonardo.ai/api/rest/v1' class-attribute instance-attribute (griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.api_base)"><code class="language-python">api_base</code></a> |
str |
The base URL of the Leonardo API.<br/> |
<a href="leonardo.mdx#griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.max_attempts" title="max_attempts = field(default=10, kw_only=True, metadata={'serializable': True}) class-attribute instance-attribute (griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.max_attempts)"><code class="language-python">max_attempts</code></a> |
int |
The maximum number of times to poll the Leonardo API for a completed image.<br/> |
<a href="leonardo.mdx#griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.image_width" title="image_width = field(default=512, kw_only=True, metadata={'serializable': True}) class-attribute instance-attribute (griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.image_width)"><code class="language-python">image_width</code></a> |
int |
The width of the generated image in the range [32, 1024] and divisible by 8.<br/> |
<a href="leonardo.mdx#griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.image_height" title="image_height = field(default=512, kw_only=True, metadata={'serializable': True}) class-attribute instance-attribute (griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.image_height)"><code class="language-python">image_height</code></a> |
int |
The height of the generated image in the range [32, 1024] and divisible by 8.<br/> |
<a href="leonardo.mdx#griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.steps" title="steps = field(default=None, kw_only=True, metadata={'serializable': True}) class-attribute instance-attribute (griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.steps)"><code class="language-python">steps</code></a> |
Optional[int] |
Optionally specify the number of inference steps to run for each image generation request, [30, 60].<br/> |
<a href="leonardo.mdx#griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.seed" title="seed = field(default=None, kw_only=True, metadata={'serializable': True}) class-attribute instance-attribute (griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.seed)"><code class="language-python">seed</code></a> |
Optional[int] |
Optionally provide a consistent seed to generation requests, increasing consistency in output.<br/> |
<a href="leonardo.mdx#griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.init_strength" title="init_strength = field(default=None, kw_only=True, metadata={'serializable': True}) class-attribute instance-attribute (griptape.drivers.image_generation.leonardo.LeonardoImageGenerationDriver.init_strength)"><code class="language-python">init_strength</code></a> |
Optional[float] |
Optionally specify the strength of the initial image, [0.0, 1.0].<br/> |
Source Code in
griptape/drivers/image_generation/leonardo_image_generation_driver.py
@define
class LeonardoImageGenerationDriver(BaseImageGenerationDriver):
"""Driver for the Leonardo image generation API.
Details on Leonardo image generation parameters can be found here:
https://docs.leonardo.ai/reference/creategeneration
Attributes:
model: The ID of the model to use when generating images.
api_key: The API key to use when making requests to the Leonardo API.
requests_session: The requests session to use when making requests to the Leonardo API.
api_base: The base URL of the Leonardo API.
max_attempts: The maximum number of times to poll the Leonardo API for a completed image.
image_width: The width of the generated image in the range [32, 1024] and divisible by 8.
image_height: The height of the generated image in the range [32, 1024] and divisible by 8.
steps: Optionally specify the number of inference steps to run for each image generation request, [30, 60].
seed: Optionally provide a consistent seed to generation requests, increasing consistency in output.
init_strength: Optionally specify the strength of the initial image, [0.0, 1.0].
"""
api_key: str = field(kw_only=True, metadata={"serializable": True})
requests_session: requests.Session = field(default=Factory(lambda: requests.Session()), kw_only=True)
api_base: str = "https://cloud.leonardo.ai/api/rest/v1"
max_attempts: int = field(default=10, kw_only=True, metadata={"serializable": True})
image_width: int = field(default=512, kw_only=True, metadata={"serializable": True})
image_height: int = field(default=512, kw_only=True, metadata={"serializable": True})
steps: Optional[int] = field(default=None, kw_only=True, metadata={"serializable": True})
seed: Optional[int] = field(default=None, kw_only=True, metadata={"serializable": True})
init_strength: Optional[float] = field(default=None, kw_only=True, metadata={"serializable": True})
control_net: bool = field(default=False, kw_only=True, metadata={"serializable": True})
control_net_type: Optional[Literal["POSE", "CANNY", "DEPTH"]] = field(
default=None,
kw_only=True,
metadata={"serializable": True},
)
def try_text_to_image(self, prompts: list[str], negative_prompts: Optional[list[str]] = None) -> ImageArtifact:
if negative_prompts is None:
negative_prompts = []
generation_id = self._create_generation(prompts=prompts, negative_prompts=negative_prompts)
image_url = self._get_image_url(generation_id=generation_id)
image_data = self._download_image(url=image_url)
return ImageArtifact(
value=image_data,
format="png",
width=self.image_width,
height=self.image_height,
meta={
"model": self.model,
"prompt": ", ".join(prompts),
},
)
def try_image_variation(
self,
prompts: list[str],
image: ImageArtifact,
negative_prompts: Optional[list[str]] = None,
) -> ImageArtifact:
if negative_prompts is None:
negative_prompts = []
init_image_id = self._upload_init_image(image)
generation_id = self._create_generation(
prompts=prompts,
negative_prompts=negative_prompts,
init_image_id=init_image_id,
)
image_url = self._get_image_url(generation_id=generation_id)
image_data = self._download_image(url=image_url)
return ImageArtifact(
value=image_data,
format="png",
width=self.image_width,
height=self.image_height,
meta={
"model": self.model,
"prompt": ", ".join(prompts),
},
)
def try_image_outpainting(
self,
prompts: list[str],
image: ImageArtifact,
mask: ImageArtifact,
negative_prompts: Optional[list[str]] = None,
) -> ImageArtifact:
raise NotImplementedError(f"{self.__class__.__name__} does not support outpainting")
def try_image_inpainting(
self,
prompts: list[str],
image: ImageArtifact,
mask: ImageArtifact,
negative_prompts: Optional[list[str]] = None,
) -> ImageArtifact:
raise NotImplementedError(f"{self.__class__.__name__} does not support inpainting")
def _upload_init_image(self, image: ImageArtifact) -> str:
request = {"extension": image.mime_type.split("/")[1]}
prep_response = self._make_api_request("/init-image", request=request)
if prep_response is None or prep_response["uploadInitImage"] is None:
raise Exception(f"failed to prepare init image: {prep_response}")
fields = json.loads(prep_response["uploadInitImage"]["fields"])
pre_signed_url = prep_response["uploadInitImage"]["url"]
init_image_id = prep_response["uploadInitImage"]["id"]
files = {"file": image.value}
upload_response = requests.post(pre_signed_url, data=fields, files=files)
if not upload_response.ok:
raise Exception(f"failed to upload init image: {upload_response.text}")
return init_image_id
def _create_generation(
self,
prompts: list[str],
negative_prompts: list[str],
init_image_id: Optional[str] = None,
) -> str:
prompt = ", ".join(prompts)
negative_prompt = ", ".join(negative_prompts)
request = {
"prompt": prompt,
"negative_prompt": negative_prompt,
"width": self.image_width,
"height": self.image_height,
"num_images": 1,
"modelId": self.model,
}
if init_image_id is not None:
request["init_image_id"] = init_image_id
if self.init_strength is not None:
request["init_strength"] = self.init_strength
if self.steps:
request["num_inference_steps"] = self.steps
if self.seed is not None:
request["seed"] = self.seed
if self.control_net:
request["controlNet"] = self.control_net
request["controlNetType"] = self.control_net_type
response = self._make_api_request("/generations", request=request)
if response is None or response["sdGenerationJob"] is None:
raise Exception(f"failed to create generation: {response}")
return response["sdGenerationJob"]["generationId"]
def _make_api_request(self, endpoint: str, request: dict, method: str = "POST") -> dict:
url = f"{self.api_base}{endpoint}"
headers = {"Authorization": f"Bearer {self.api_key}"}
response = self.requests_session.request(url=url, method=method, json=request, headers=headers)
if not response.ok:
raise Exception(f"failed to make API request: {response.text}")
return response.json()
def _get_image_url(self, generation_id: str) -> str:
for attempt in range(self.max_attempts):
response = self.requests_session.get(
url=f"{self.api_base}/generations/{generation_id}",
headers={"Authorization": f"Bearer {self.api_key}"},
).json()
if response["generations_by_pk"]["status"] == "PENDING":
time.sleep(attempt + 1)
continue
return response["generations_by_pk"]["generated_images"][0]["url"]
raise Exception("image generation failed to complete")
def _download_image(self, url: str) -> bytes:
response = self.requests_session.get(url=url, headers={"Authorization": f"Bearer {self.api_key}"})
return response.content
api_base = 'https://cloud.leonardo.ai/api/rest/v1'class-attribute instance-attributeapi_key = field(kw_only=True, metadata={'serializable': True})class-attribute instance-attributecontrol_net = field(default=False, kw_only=True, metadata={'serializable': True})class-attribute instance-attributecontrol_net_type = field(default=None, kw_only=True, metadata={'serializable': True})class-attribute instance-attributeimage_height = field(default=512, kw_only=True, metadata={'serializable': True})class-attribute instance-attributeimage_width = field(default=512, kw_only=True, metadata={'serializable': True})class-attribute instance-attributeinit_strength = field(default=None, kw_only=True, metadata={'serializable': True})class-attribute instance-attributemax_attempts = field(default=10, kw_only=True, metadata={'serializable': True})class-attribute instance-attributerequests_session = field(default=Factory(lambda: requests.Session()), kw_only=True)class-attribute instance-attributeseed = field(default=None, kw_only=True, metadata={'serializable': True})class-attribute instance-attributesteps = field(default=None, kw_only=True, metadata={'serializable': True})class-attribute instance-attribute
_create_generation(prompts, negative_prompts, init_image_id=None)#
Source Code in
griptape/drivers/image_generation/leonardo_image_generation_driver.py
def _create_generation(
self,
prompts: list[str],
negative_prompts: list[str],
init_image_id: Optional[str] = None,
) -> str:
prompt = ", ".join(prompts)
negative_prompt = ", ".join(negative_prompts)
request = {
"prompt": prompt,
"negative_prompt": negative_prompt,
"width": self.image_width,
"height": self.image_height,
"num_images": 1,
"modelId": self.model,
}
if init_image_id is not None:
request["init_image_id"] = init_image_id
if self.init_strength is not None:
request["init_strength"] = self.init_strength
if self.steps:
request["num_inference_steps"] = self.steps
if self.seed is not None:
request["seed"] = self.seed
if self.control_net:
request["controlNet"] = self.control_net
request["controlNetType"] = self.control_net_type
response = self._make_api_request("/generations", request=request)
if response is None or response["sdGenerationJob"] is None:
raise Exception(f"failed to create generation: {response}")
return response["sdGenerationJob"]["generationId"]
_download_image(url)#
Source Code in
griptape/drivers/image_generation/leonardo_image_generation_driver.py
def _download_image(self, url: str) -> bytes:
response = self.requests_session.get(url=url, headers={"Authorization": f"Bearer {self.api_key}"})
return response.content
_get_image_url(generation_id)#
Source Code in
griptape/drivers/image_generation/leonardo_image_generation_driver.py
def _get_image_url(self, generation_id: str) -> str:
for attempt in range(self.max_attempts):
response = self.requests_session.get(
url=f"{self.api_base}/generations/{generation_id}",
headers={"Authorization": f"Bearer {self.api_key}"},
).json()
if response["generations_by_pk"]["status"] == "PENDING":
time.sleep(attempt + 1)
continue
return response["generations_by_pk"]["generated_images"][0]["url"]
raise Exception("image generation failed to complete")
_make_api_request(endpoint, request, method=‘POST’)#
Source Code in
griptape/drivers/image_generation/leonardo_image_generation_driver.py
def _make_api_request(self, endpoint: str, request: dict, method: str = "POST") -> dict:
url = f"{self.api_base}{endpoint}"
headers = {"Authorization": f"Bearer {self.api_key}"}
response = self.requests_session.request(url=url, method=method, json=request, headers=headers)
if not response.ok:
raise Exception(f"failed to make API request: {response.text}")
return response.json()
_upload_init_image(image)#
Source Code in
griptape/drivers/image_generation/leonardo_image_generation_driver.py
def _upload_init_image(self, image: ImageArtifact) -> str:
request = {"extension": image.mime_type.split("/")[1]}
prep_response = self._make_api_request("/init-image", request=request)
if prep_response is None or prep_response["uploadInitImage"] is None:
raise Exception(f"failed to prepare init image: {prep_response}")
fields = json.loads(prep_response["uploadInitImage"]["fields"])
pre_signed_url = prep_response["uploadInitImage"]["url"]
init_image_id = prep_response["uploadInitImage"]["id"]
files = {"file": image.value}
upload_response = requests.post(pre_signed_url, data=fields, files=files)
if not upload_response.ok:
raise Exception(f"failed to upload init image: {upload_response.text}")
return init_image_id
try_image_inpainting(prompts, image, mask, negative_prompts=None)#
Source Code in
griptape/drivers/image_generation/leonardo_image_generation_driver.py
def try_image_inpainting(
self,
prompts: list[str],
image: ImageArtifact,
mask: ImageArtifact,
negative_prompts: Optional[list[str]] = None,
) -> ImageArtifact:
raise NotImplementedError(f"{self.__class__.__name__} does not support inpainting")
try_image_outpainting(prompts, image, mask, negative_prompts=None)#
Source Code in
griptape/drivers/image_generation/leonardo_image_generation_driver.py
def try_image_outpainting(
self,
prompts: list[str],
image: ImageArtifact,
mask: ImageArtifact,
negative_prompts: Optional[list[str]] = None,
) -> ImageArtifact:
raise NotImplementedError(f"{self.__class__.__name__} does not support outpainting")
try_image_variation(prompts, image, negative_prompts=None)#
Source Code in
griptape/drivers/image_generation/leonardo_image_generation_driver.py
def try_image_variation(
self,
prompts: list[str],
image: ImageArtifact,
negative_prompts: Optional[list[str]] = None,
) -> ImageArtifact:
if negative_prompts is None:
negative_prompts = []
init_image_id = self._upload_init_image(image)
generation_id = self._create_generation(
prompts=prompts,
negative_prompts=negative_prompts,
init_image_id=init_image_id,
)
image_url = self._get_image_url(generation_id=generation_id)
image_data = self._download_image(url=image_url)
return ImageArtifact(
value=image_data,
format="png",
width=self.image_width,
height=self.image_height,
meta={
"model": self.model,
"prompt": ", ".join(prompts),
},
)
try_text_to_image(prompts, negative_prompts=None)#
Source Code in
griptape/drivers/image_generation/leonardo_image_generation_driver.py
def try_text_to_image(self, prompts: list[str], negative_prompts: Optional[list[str]] = None) -> ImageArtifact:
if negative_prompts is None:
negative_prompts = []
generation_id = self._create_generation(prompts=prompts, negative_prompts=negative_prompts)
image_url = self._get_image_url(generation_id=generation_id)
image_data = self._download_image(url=image_url)
return ImageArtifact(
value=image_data,
format="png",
width=self.image_width,
height=self.image_height,
meta={
"model": self.model,
"prompt": ", ".join(prompts),
},
)