Amazon Bedrock: Stability AI: 画像生成

Amazon Bedrock: Stability AI: 画像生成

Amazon Bedrock: Stability AI: Generate Image

この工程は、Amazon Bedrock 上で動作する Stability AI の モデルを用いて、画像を生成します。

Basic Configs
工程名
メモ
Auto Step icon
Configs for this Auto Step
conf_AccessKey
C1: アクセスキー *
conf_SecretKey
C2: シークレットアクセスキー *
conf_Region
C3: リージョンコード *
conf_Model
C4: モデル *
conf_Prompt
C5: プロンプト *#{EL}
conf_Negative
C6: ネガティブプロンプト#{EL}
conf_Seed
C7: シードを保持している/保存するデータ項目
conf_Aspect
C8: 画像アスペクト比 (未設定の場合、1:1)
conf_Format
C9: 画像形式 (未設定の場合、PNG)
conf_File
C10: 生成されたファイルを追加保存するデータ項目 *
conf_FileName
C11: 保存する際のファイル名 *#{EL}

Notes

Capture

See Also

Script (click to open)
  • 次のスクリプトが記述されている XML ファイルをダウンロードできます
    • aws-bedrock-stability-ai-image-generate.xml (C) Questetra, Inc. (MIT License)
    • Professional のワークフロー基盤では、ファイル内容を改変しオリジナルのアドオン自動工程として活用できます

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 model = retrieveModel();
    const payload = buildPayload();
    const fileName = configs.get("conf_FileName");
    if (fileName === "") {
        throw new Error("File name is blank.");
    }
    //ファイル名が200文字を超えていないか
    if(fileName.length > 200){
        throw new Error("File Name should be less than 200 characters");
    }


    ////// == 演算 / Calculating ==
    const { generatedFile, seed } = generateImage(awsKey, awsSecret, region, model, 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 からモデル ID を読み出す
 * モデル ID として不正な場合はエラー
 * @return {String}
 */
function retrieveModel() {
    const model = configs.get('conf_Model');
    const reg = new RegExp('^[a-z0-9.:-]+$');
    if (!reg.test(model)) {
        throw new Error('Model is invalid. It contains an invalid character.');
    }
    const MODEL_PREFIX = 'stability';
    if (!model.startsWith(MODEL_PREFIX)){
        throw new Error(`Model is invalid. It must start with "${MODEL_PREFIX}".`);
    }
    return model;
}

/**
 * config から API リクエストのボティにセットするパラメータを読み出し、
 * ペイロードを構築する
 * @return {Object}
 */
const buildPayload = () => {
    const payload = {
        prompt: retrieveTextPrompts(),
        seed: retrieveSeed()
    };

    const negative = configs.get('conf_Negative');
    if (negative !== '') {
        Object.assign(payload, {
            negative_prompt: negative
        });
    }

    const aspect = configs.get("conf_Aspect");
    if (aspect !== '') {
        Object.assign(payload, {
            aspect_ratio: aspect
        });
    }

    let format = 'png'
    if (configs.get("conf_Format") === 'jpg') {
        format = 'jpg'
    }
    Object.assign(payload, {
        output_format: format
    });

    engine.log(JSON.stringify(payload));
    return payload;
}

/**
 * config からテキストプロンプトを読み出す
 * @return {Array}
 */
const retrieveTextPrompts = () => {
    const prompt = configs.get('conf_Prompt');
    if (prompt === '') {
        throw new Error('Prompt is blank.');
    }
    return prompt;
};


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, model, 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 responsesBody = JSON.parse(respTxt);
    engine.log(JSON.stringify(Object.assign({},responsesBody, { // images 以外の値をログ出力
        images: undefined
    })));
    const image = base64.decodeFromStringToByteArray(responsesBody.images[0]);

    let format = "png";
    if (payload.output_format === "jpg"){
        format = "jpg"
    }

    const generatedFile = new com.questetra.bpms.core.event.scripttask.NewQfile(
        fileName,
        `image/${format}`,
        image
    );
    const seed = String(responsesBody.seeds[0])
    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);
};

    
上部へスクロール

Questetra Supportをもっと見る

今すぐ購読し、続きを読んで、すべてのアーカイブにアクセスしましょう。

続きを読む