(Deprecated) AWS: Stable Diffusion 1.0: Generate Image

infoThis item has been deprecated

Use the successor: Amazon Bedrock: Stability AI: Generate Image

(Deprecated) AWS: Stable Diffusion 1.0: Generate Image

(廃止予定) AWS: Stable Diffusion 1.0: 画像生成

This item generates an image using Stability AI’s Stable Diffusion 1.0 on Amazon Bedrock.

Auto Step icon
Basic Configs
Step Name
Note
Configs for this Auto Step
conf_AccessKey
C1: Access Key *
conf_SecretKey
C2: Secret Access Key *
conf_Region
C3: Region Code *
conf_Message
C4: Prompt *#{EL}
conf_Negative
C5: Negative Prompt#{EL}
conf_Size
C6-a: Image Size
conf_InitImage
C6-b: Data item that stores a base image file
conf_Style
C7: Image Style
conf_Seed
C8: Data item that stores / to save the seed
conf_File
C9: Data item to add the generated file *
conf_FileName
C10: File name to save as *#{EL}
Auto Step icon
Configs for this Auto Step
conf_AccessKey
C1: Access Key *
conf_SecretKey
C2: Secret Access Key *
conf_Region
C3: Region Code *
conf_Message
C4: Prompt *#{EL}
conf_Negative
C5: Negative Prompt#{EL}
conf_Size
C6-a: Image Size
conf_InitImage
C6-b: Data item that stores a base image file
conf_Style
C7: Image Style
conf_Seed
C8: Data item that stores / to save the seed
conf_File
C9: Data item to add the generated file *
conf_FileName
C10: File name to save as *#{EL}

Notes

  • To learn about how to create your Access Key and Secret Access Key, see the Amazon Web Services Documentation
  • If you have specified a base image in [C6-b: Data item that stores a base image file], the configuration of [C6-a: Image Size] will be ignored

Capture

See Also

Script (click to open)
  • An XML file that contains the code below is available to download

const MODEL = "stability.stable-diffusion-xl-v1";
const SERVICE = "bedrock";

function main() {
    ////// == 工程コンフィグ・ワークフローデータの参照 / Config & Data Retrieving ==
    const awsKey = configs.getObject("conf_AccessKey").getToken();
    const awsSecret = configs.getObject("conf_SecretKey").getToken();
    const region = retrieveRegion();
    const payload = buildPayload();
    const fileName = configs.get("conf_FileName");
    if (fileName === "") {
        throw new Error("File name is blank.");
    }

    ////// == 演算 / Calculating ==
    const { generatedFile, seed } = generateImage(awsKey, awsSecret, region, payload, fileName);

    ////// == ワークフローデータへの代入 / Data Updating ==
    saveFileData('conf_File', generatedFile);
    saveData('conf_Seed', seed);
}

/**
 * config からリージョンコードを読み出す
 * リージョンコードの形式として不正な場合はエラー
 * @return {String}
 */
const retrieveRegion = () => {
    const region = configs.get("conf_Region");
    // 今後リージョンが増えることも考えて、中央の最大文字数には余裕をみている
    const reg = new RegExp("^[a-z]{2}-[a-z]{4,16}-[1-9]$");
    if (!reg.test(region)) {
        throw new Error("Region Code is invalid.");
    }
    return region;
}

/**
 * config から API リクエストのボティにセットするパラメータを読み出し、
 * ペイロードを構築する
 * @return {Object}
 */
const buildPayload = () => {
    // cfg_scale / steps は stability.ai のデフォルト値で行く
    const payload = {
        text_prompts: retrieveTextPrompts(),
        seed: retrieveSeed(),
        style_preset: retrieveStyle()
    };

    const initImage = retrieveInitImage();
    const size = retrieveImageSize();
    if (initImage !== null) {
        Object.assign(payload, {
            init_image: initImage
        });
    } else if (size !== null) { // init_image がある場合は size は無視される
        Object.assign(payload, {
            width: size.width,
            height: size.height
        });
    }
    return payload;
}

/**
 * config からテキストプロンプトとネガティブプロンプトを読み出す
 * @return {Array}
 */
const retrieveTextPrompts = () => {
    const message = configs.get('conf_Message');
    if (message === '') {
        throw new Error('Prompt is blank.');
    }
    const negative = configs.get('conf_Negative');

    const prompts = [{
        text: message,
        weight: 1.0
    }];
    if (negative !== '') {
        prompts.push({
            text: negative,
            weight: -0.5
        });
    }
    return prompts;
};

/**
 * config から画像サイズを読み出す
 * @return {Object} {width, height}
 */
const retrieveImageSize = () => {
    const size = configs.get("conf_Size");
    if (size === "") {
        return null;
    }
    const width = Number.parseInt(size.split("x")[0]);
    const height = Number.parseInt(size.split("x")[1]);
    return {
        width,
        height
    };
};

/**
 * config からベースとする画像を読み出し、base64 エンコードして返す
 * @return {String} base64 エンコードされた画像
 */
const retrieveInitImage = () => {
    const imageDef = configs.getObject("conf_InitImage");
    if (imageDef === null) {
        return null;
    }
    const images = engine.findData(imageDef);
    if (images === null) {
        return null;
    }
    if (images.size() !== 1) {
        throw new Error("More than one base image files attached.");
    }
    const image = images.get(0);
    if (!image.getContentType().startsWith('image/')) {
        throw new Error("The base image file is not an image.");
    }
    // 幅、高さがそれぞれ 64 の倍数である必要があるが、事前に確認するのは難しいので、API に任せる
    return base64.encodeToString(fileRepository.readFile(image));
};

/**
 * config から画像スタイルを読み出す
 * @return {String}
 */
const retrieveStyle = () => {
    const style = configs.get("conf_Style");
    if (style === "") {
        return undefined;
    }
    return style;
};

const MAX_SEED = 4294967295;

/**
 * config からシードを読み出す
 * @return {Number}
 */
const retrieveSeed = () => {
    const seedDef = configs.getObject("conf_Seed");
    if (seedDef === null) {
        return undefined;
    }
    const seed = engine.findData(seedDef);
    if (seed === null) {
        return undefined;
    }
    const reg = new RegExp('^(0|[1-9][0-9]{0,9})$');
    const errorMsg = `Seed must be an integer from 0 to ${MAX_SEED}.`;
    if (!reg.test(seed)) {
        throw new Error(errorMsg);
    }
    const seedNum = Number.parseInt(seed);
    if (seedNum > MAX_SEED) {
        throw new Error(errorMsg);
    }
    return seedNum;
};

/**
 * 画像を生成する API リクエストを送信
 * @param awsKey
 * @param awsSecret
 * @param region
 * @param payload
 * @param fileName
 * @return {Object} {generatedFile: NewQfile, seed: String}
 */
const generateImage = (awsKey, awsSecret, region, payload, fileName) => {
    const URL = `https://bedrock-runtime.${region}.amazonaws.com/model/${MODEL}/invoke`;
    const response = httpClient.begin()
        .awsSignV4(awsKey, awsSecret, region, SERVICE)
        .body(JSON.stringify(payload), "application/json")
        .post(URL);

    const status = response.getStatusCode();
    const respTxt = response.getResponseAsString();
    if (status !== 200) {
        engine.log(respTxt);
        throw new Error(`Failed to invoke model. status: ${status}`);
    }

    const {artifacts} = JSON.parse(respTxt);
    engine.log(JSON.stringify(Object.assign({}, artifacts[0], { // base64 以外の値をログ出力
        base64: undefined
    })));
    const image = base64.decodeFromStringToByteArray(artifacts[0].base64);
    const generatedFile = new com.questetra.bpms.core.event.scripttask.NewQfile(
        fileName,
        "image/png",
        image
    );
    const seed = String(artifacts[0].seed)
    return { generatedFile, seed };
};

/**
 * データ項目への保存
 * @param configName
 * @param newFile
 */
const saveFileData = (configName, newFile) => {
    const def = configs.getObject(configName);
    if (def === null) {
        return;
    }
    let files = engine.findData(def);
    if (files === null) {
        files = new java.util.ArrayList();
    }
    files.add(newFile);
    engine.setData(def, files);
};

/**
 * データ項目への保存
 * @param configName
 * @param data
 */
const saveData = (configName, data) => {
    const def = configs.getObject(configName);
    if (def === null) {
        return;
    }
    engine.setData(def, data);
};

    
Scroll to Top

Discover more from Questetra Support

Subscribe now to keep reading and get access to the full archive.

Continue reading