Skip to content

Commit 8b4f66c

Browse files
Changes per PR Review
1 parent 72c48a3 commit 8b4f66c

File tree

8 files changed

+102
-175
lines changed

8 files changed

+102
-175
lines changed

components/leonardo_ai/README.md

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,6 @@
22

33
[Leonardo AI](https://leonardo.ai) is an AI-powered image generation platform that allows you to create stunning images, videos, and 3D models using advanced machine learning models.
44

5-
## Authentication
6-
7-
To use this component, you'll need to:
8-
9-
1. Sign up for a Leonardo AI account at [leonardo.ai](https://leonardo.ai)
10-
2. Navigate to the API section in your account settings
11-
3. Create an API key
12-
4. Use this API key when connecting the Leonardo AI app in Pipedream
13-
145
## Actions
156

167
### Generate Image
@@ -42,11 +33,6 @@ Creates unzoom variations of existing images, expanding the scene beyond the ori
4233
### Upload Image
4334
Uploads images to Leonardo AI for use in generations and variations.
4435

45-
**Key Features:**
46-
- Support for image URLs
47-
- Optional image naming
48-
- Integration with other Leonardo AI actions
49-
5036
### Upscale Image
5137
Increases the resolution of images using Leonardo AI's Universal Upscaler.
5238

@@ -99,11 +85,7 @@ For detailed information about Leonardo AI's API, visit the [official documentat
9985

10086
## Rate Limits
10187

102-
Leonardo AI has the following rate limits:
103-
- Total requests: 1,000 per minute
104-
- Image generation requests: 100 per minute
105-
- Concurrent image generation jobs: 10
106-
- Concurrent model training jobs: 5
88+
See the official Leonardo AI documentation for current limits.
10789

10890
## Support
10991

components/leonardo_ai/actions/generate-image/generate-image.mjs

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import app from "../../leonardo_ai.app.mjs";
33
export default {
44
key: "leonardo_ai-generate-image",
55
name: "Generate Image",
6-
description: "Generates new images using Leonardo AI's image generation API.",
7-
version: "0.0.5",
6+
description: "Generates new images using Leonardo AI's image generation API. [See the documentation](https://docs.leonardo.ai/reference/creategeneration)",
7+
version: "0.0.1",
88
type: "action",
99
props: {
1010
app,
@@ -18,7 +18,7 @@ export default {
1818
label: "Model",
1919
description: "The model to use for generation. Leave empty to use the default model.",
2020
async options() {
21-
const models = await this.app.getPlatformModels({});
21+
const models = await this.app.getPlatformModels();
2222
return models.map((model) => ({
2323
label: model.name || model.id,
2424
value: model.id,
@@ -30,39 +30,42 @@ export default {
3030
type: "integer",
3131
label: "Width",
3232
description: "Width of the generated image in pixels.",
33-
default: 512,
34-
min: 256,
35-
max: 1024,
33+
default: 1024,
34+
min: 32,
35+
max: 1536,
3636
},
3737
height: {
3838
type: "integer",
3939
label: "Height",
4040
description: "Height of the generated image in pixels.",
41-
default: 512,
42-
min: 256,
43-
max: 1024,
41+
default: 768,
42+
min: 32,
43+
max: 1536,
4444
},
4545
numImages: {
4646
type: "integer",
4747
label: "Number of Images",
48-
description: "Number of images to generate (1-4).",
48+
description: "Number of images to generate (1-8). If either width or height is over 768, must be between 1 and 4.",
4949
default: 1,
5050
min: 1,
51-
max: 4,
51+
max: 8,
5252
},
5353
guidanceScale: {
54-
type: "string",
54+
type: "integer",
5555
label: "Guidance Scale",
5656
description: "How closely the model should follow the prompt. Must be between 1 and 20. Higher values = more adherence to prompt.",
57+
default: 7,
58+
min: 1,
59+
max: 20,
5760
optional: true,
5861
},
5962
numInferenceSteps: {
6063
type: "integer",
6164
label: "Inference Steps",
6265
description: "Number of denoising steps. More steps = higher quality but slower generation.",
63-
default: 20,
66+
default: 15,
6467
min: 10,
65-
max: 50,
68+
max: 60,
6669
optional: true,
6770
},
6871
seed: {
@@ -89,28 +92,20 @@ export default {
8992
width,
9093
height,
9194
num_images: numImages,
95+
modelId,
96+
guidance_scale: guidanceScale,
97+
num_inference_steps: numInferenceSteps,
98+
seed: seed
9299
};
93100

94-
if (modelId) {
95-
data.modelId = modelId;
96-
}
97-
if (guidanceScale) {
98-
data.guidance_scale = parseFloat(guidanceScale);
99-
}
100-
if (numInferenceSteps) {
101-
data.num_inference_steps = numInferenceSteps;
102-
}
103-
if (seed) {
104-
data.seed = seed;
105-
}
106-
107-
const response = await this.app.post({
101+
const response = await this.app._makeRequest({
108102
$,
103+
method: "POST",
109104
path: "/generations",
110105
data,
111106
});
112107

113-
$.export("$summary", `Successfully generated ${numImages} image(s) with prompt: "${prompt}"`);
108+
$.export("$summary", `Successfully generated ${numImages} image(s)`);
114109
return response;
115110
},
116111
};

components/leonardo_ai/actions/generate-motion/generate-motion.mjs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import app from "../../leonardo_ai.app.mjs";
33
export default {
44
key: "leonardo_ai-generate-motion",
55
name: "Generate Motion",
6-
description: "Generates a motion (video) from the provided image using Leonardo AI's SVD Motion Generation API.",
7-
version: "0.0.4",
6+
description: "Generates a motion (video) from the provided image using Leonardo AI's SVD Motion Generation API. [See the documentation](https://docs.leonardo.ai/reference/createsvdmotiongeneration)",
7+
version: "0.0.1",
88
type: "action",
99
props: {
1010
app,
@@ -28,13 +28,13 @@ export default {
2828
isInitImage: {
2929
type: "boolean",
3030
label: "Is Init Image",
31-
description: "If it is an init image uploaded by the user.",
31+
description: "Whether the image being used is an init image uploaded by the user.",
3232
optional: true,
3333
},
3434
isVariation: {
3535
type: "boolean",
3636
label: "Is Variation",
37-
description: "If it is a variation image.",
37+
description: "Whether the image being used is a variation image.",
3838
optional: true,
3939
},
4040
},
@@ -49,23 +49,15 @@ export default {
4949

5050
const data = {
5151
imageId,
52+
motionStrength,
53+
isPublic,
54+
isInitImage,
55+
isVariation,
5256
};
5357

54-
if (motionStrength !== undefined) {
55-
data.motionStrength = motionStrength;
56-
}
57-
if (isPublic !== undefined) {
58-
data.isPublic = isPublic;
59-
}
60-
if (isInitImage !== undefined) {
61-
data.isInitImage = isInitImage;
62-
}
63-
if (isVariation !== undefined) {
64-
data.isVariation = isVariation;
65-
}
66-
67-
const response = await this.app.post({
58+
const response = await this.app._makeRequest({
6859
$,
60+
method: "POST",
6961
path: "/generations-motion-svd",
7062
data,
7163
});

components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import app from "../../leonardo_ai.app.mjs";
33
export default {
44
key: "leonardo_ai-unzoom-image",
55
name: "Unzoom Image",
6-
description: "Creates an unzoom variation for a generated or variation image using Leonardo AI's unzoom API.",
7-
version: "0.0.2",
6+
description: "Creates an unzoom variation for a generated or variation image using Leonardo AI's unzoom API. [See the documentation](https://docs.leonardo.ai/reference/createvariationunzoom)",
7+
version: "0.0.1",
88
type: "action",
99
props: {
1010
app,
@@ -31,8 +31,9 @@ export default {
3131
isVariation,
3232
};
3333

34-
const response = await this.app.post({
34+
const response = await this.app._makeRequest({
3535
$,
36+
method: "POST",
3637
path: "/variations/unzoom",
3738
data,
3839
});

components/leonardo_ai/actions/upload-image/upload-image.mjs

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import app from "../../leonardo_ai.app.mjs";
2+
import FormData from "form-data";
3+
import { getFileStreamAndMetadata } from "@pipedream/platform";
24

35
export default {
46
key: "leonardo_ai-upload-image",
57
name: "Upload Image",
6-
description: "Uploads a new image to Leonardo AI for use in generations and variations.",
7-
version: "0.0.9",
8+
description: "Uploads a new image to Leonardo AI for use in generations and variations. [See the documentation](https://docs.leonardo.ai/docs/how-to-upload-an-image-using-a-presigned-url)",
9+
version: "0.0.1",
810
type: "action",
911
props: {
1012
app,
@@ -31,52 +33,58 @@ export default {
3133
},
3234
],
3335
},
34-
file: {
36+
filePath: {
3537
type: "string",
36-
label: "File",
37-
description: "The base64 encoded image file to upload.",
38+
label: "File Path or URL",
39+
description: "The file to upload. Provide either a file URL or a path to a file in the `/tmp` directory (for example, `/tmp/myImage.png`)",
40+
},
41+
syncDir: {
42+
type: "dir",
43+
accessMode: "read",
44+
sync: true,
45+
optional: true,
3846
},
3947
},
4048
async run({ $ }) {
4149
const {
4250
extension,
43-
file,
51+
filePath,
4452
} = this;
45-
console.log(extension);
46-
// Convert base64 string to Buffer
47-
const base64Data = file.replace(/^data:image\/[a-z]+;base64,/, "");
48-
const buffer = Buffer.from(base64Data, "base64");
49-
50-
// Create a File-like object from the buffer
51-
const fileObject = {
52-
buffer: buffer,
53-
name: `image.${extension}`,
54-
type: `image/${
55-
extension === "jpg" ?
56-
"jpeg"
57-
: extension
58-
}`,
59-
};
53+
// Get file stream from URL or /tmp based path
54+
const {
55+
stream,
56+
metadata,
57+
} = await getFileStreamAndMetadata(filePath);
6058

61-
// Step 1: Get the presigned URL and upload fields
59+
// Step 1: Get the presigned URL, upload fields appended to formData
6260
const uploadResponse = await this.app.getUploadInitImage({
6361
$,
6462
extension,
6563
});
6664

6765
const { uploadInitImage } = uploadResponse;
6866
const fields = JSON.parse(uploadInitImage.fields);
67+
const formData = new FormData();
68+
69+
//Important: Order of fields is sanctioned by Leonardo AI API. Fields should go first, then the file
70+
for (const [label, value] of Object.entries(fields)) {
71+
formData.append(label, value.toString());
72+
}
73+
formData.append("file", stream, {
74+
contentType: metadata.contentType,
75+
knownLength: metadata.size,
76+
filename: metadata.name,
77+
});
6978
const uploadUrl = uploadInitImage.url;
7079

7180
// Step 2: Upload the file to the presigned URL
7281
const uploadResult = await this.app.uploadFileToPresignedUrl({
7382
$,
7483
url: uploadUrl,
75-
fields,
76-
file: fileObject,
84+
formData,
7785
});
7886

79-
$.export("$summary", `Successfully uploaded image with extension: ${extension}`);
87+
$.export("$summary", `Successfully uploaded image: ${metadata.name || filePath}`);
8088
return {
8189
uploadInitImage,
8290
uploadResult,

components/leonardo_ai/actions/upscale-image/upscale-image.mjs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import app from "../../leonardo_ai.app.mjs";
33
export default {
44
key: "leonardo_ai-upscale-image",
55
name: "Upscale Image",
6-
description: "Creates a high-resolution upscale of the provided image using Leonardo AI's upscale API.",
7-
version: "0.0.2",
6+
description: "Creates a high-resolution upscale of the provided image using Leonardo AI's upscale API. [See the documentation](https://docs.leonardo.ai/reference/createvariationupscale)",
7+
version: "0.0.1",
88
type: "action",
99
props: {
1010
app,
@@ -21,8 +21,9 @@ export default {
2121
id: imageId,
2222
};
2323

24-
const response = await this.app.post({
24+
const response = await this.app._makeRequest({
2525
$,
26+
method: "POST",
2627
path: "/variations/upscale",
2728
data,
2829
});

0 commit comments

Comments
 (0)