From 3f6e269f029a838d25c8aa3d80fc2c1f69717aa8 Mon Sep 17 00:00:00 2001 From: Greg Johns <> Date: Fri, 27 Oct 2023 01:43:28 -0400 Subject: [PATCH] added stability text-to-image job --- .env.example | 3 ++ package.json | 1 + src/stability.ts | 100 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 src/stability.ts diff --git a/.env.example b/.env.example index dace184..9fbb810 100644 --- a/.env.example +++ b/.env.example @@ -47,3 +47,6 @@ ASANA_ACCESS_TOKEN= ## DeepL DEEPL_AUTH_KEY= DEEPL_BASE_URL=https://api-free.deepl.com/v2/ + +# Stability +STABILITY_API_KEY= \ No newline at end of file diff --git a/package.json b/package.json index d7c8c07..8ec2e32 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "shopify": "node -r dotenv/config -r ts-node/register src/shopify.ts", "gmail": "node -r dotenv/config -r ts-node/register src/gmail.ts", "hubspot": "node -r dotenv/config -r ts-node/register src/hubspot.ts", + "stability": "node -r dotenv/config -r ts-node/register src/stability.ts", "x": "node -r dotenv/config -r ts-node/register src/x.ts", "dev:trigger": "trigger-cli dev --port 8080" }, diff --git a/src/stability.ts b/src/stability.ts new file mode 100644 index 0000000..1e0cf95 --- /dev/null +++ b/src/stability.ts @@ -0,0 +1,100 @@ +import { TriggerClient, eventTrigger } from "@trigger.dev/sdk"; +import { z } from "zod"; + +const client = new TriggerClient({ id: "api-reference" }); + +// This code uses the REST API for Stability AI +// Documentation can be found at: https://platform.stability.ai/docs/api-reference +const engineId = "stable-diffusion-xl-1024-v1-0"; +const apiHost = process.env.API_HOST ?? "https://api.stability.ai"; +const apiKey = process.env.STABILITY_API_KEY; + +interface GenerationResponse { + artifacts: Array<{ + base64: string; + seed: number; + finishReason: string; + }>; +} + +client.defineJob({ + id: "stability-ai-text-to-image", + name: "Stability AI Text to Image", + version: "1.0.0", + trigger: eventTrigger({ + name: "stability.text.to.image", + // Define the schema for text prompts used for image generation. + // Weights can be positive or negative to influence the generation. + // + // text_prompts: [ + // { + // "text": "A painting of a cat", + // "weight": 1 + // }, + // { + // "text": "blurry, bad", + // "weight": -1 + // } + // ] + // + // For more details, refer to the text-to-image endpoint documentation: + // https://platform.stability.ai/docs/api-reference#tag/v1generation/operation/textToImage + schema: z.object({ + text_prompts: z.array( + z.object({ + text: z.string(), + weight: z.number().optional(), + }) + ), + cfg_scale: z.number().optional(), + width: z.number().optional(), + height: z.number().optional(), + steps: z.number().optional(), + samples: z.number().optional(), + }), + }), + run: async (payload, io, ctx) => { + const images = await io.runTask( + "Create image from text", + async () => { + const response = await fetch( + `${apiHost}/v1/generation/${engineId}/text-to-image`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + Authorization: `Bearer ${apiKey}`, + }, + body: JSON.stringify({ + text_prompts: payload.text_prompts, + cfg_scale: payload.cfg_scale ?? 7, + height: payload.height ?? 1024, + width: payload.width ?? 1024, + steps: payload.steps ?? 50, + samples: payload.samples ?? 1, + }), + } + ); + + return response.json() as Promise; + }, + { name: "Create image from text", icon: "stability" } + ); + + // Do something with the image + await io.runTask("Save image", async () => { + images.artifacts.forEach((image, index) => { + const imageUrl = `data:image/png;base64,${image.base64}`; + // Log the URL to the console + io.logger.info(`Image ${index + 1}/${payload.samples ?? 1}:`, { + imageUrl, + }); + }); + }); + }, +}); + +// These lines can be removed if you don't want to use express +import { createExpressServer } from "@trigger.dev/express"; +createExpressServer(client);