(C) Questetra, Inc. (MIT License)
2025-09-01
3
2
https://support.questetra.com/bpmn-icons/service-task-openai-dalle-image-generate/
https://support.questetra.com/ja/bpmn-icons/service-task-openai-dalle-image-generate/
This item generates an image using OpenAI's model.
この工程は、OpenAI のモデルを用いて、画像を生成します。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
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
AAAAAElFTkSuQmCC
} files
* @returns {DataDefinitionView} fileDef
*/
const prepareConfigs = (authKey, organizationId, model, prompt, size, format, style, quality, fileName, files) => {
const authSetting = httpClient.createAuthSettingToken('ChatGPT', authKey);
configs.putObject('conf_Auth', authSetting);
configs.put('conf_OrganizationId', organizationId);
configs.put('conf_Model', model);
configs.put('conf_Prompt', prompt);
configs.put('conf_Size', size);
configs.put('conf_Format', format);
configs.put('conf_Style', style);
configs.put('conf_Quality', quality);
configs.put('conf_FileName', fileName);
const fileDef = engine.createDataDefinition('ファイル', 1, 'q_file', 'FILE');
engine.setData(fileDef, files);
configs.putObject('conf_File', fileDef);
return fileDef;
};
/**
* 異常系のテスト
* @param errorMsg
*/
const assertError = (errorMsg) => {
let failed = false;
try {
main();
} catch (e) {
failed = true;
expect(e.toString()).containsString(errorMsg);
}
if (!failed) {
fail('No error was thrown.');
}
};
/**
* OraganizationId が不正
* マルチバイト文字を含む
*/
test('OrganizationId is invalid', () => {
prepareConfigs('key', 'そしき', 'dall-e-2', 'Prompt', '512x512', '', '', '', 'test.png', null);
assertError("node.event.intermediate.message.throwing.http.header.invalid");
});
/**
* プロンプトが空
*/
test('Prompt is empty', () => {
prepareConfigs('key', '', 'dall-e-2', '', '512x512', '', '', '', 'test.png', null);
assertError('Prompt is empty.');
});
/**
* ファイル名が空
*/
test('FileName is empty', () => {
prepareConfigs('key', '', 'dall-e-2', 'Prompt', '512x512', '', '', '', '', null);
assertError('File name is empty.');
});
/**
* API リクエストのテスト
* @param {Object} request
* @param request.url
* @param request.method
* @param request.contentType
* @param request.headers
* @param request.body
* @param {String} authKey
* @param {String} organizationId
* @param {String} model
* @param {String} prompt
* @param {String} size
* @param {String} format
* @param {String} style
* @param {String} quality
*/
const assertRequest = ({
url,
method,
contentType,
headers,
body
}, authKey, organizationId, model, prompt, size, format, style, quality) => {
expect(url).toEqual('https://api.openai.com/v1/images/generations');
expect(method).toEqual('POST');
expect(contentType).toEqual('application/json');
expect(headers['Authorization']).toEqual(`Bearer ${authKey}`);
if (organizationId !== '') {
expect(headers['OpenAI-Organization']).toEqual(organizationId);
}
const bodyObj = JSON.parse(body);
expect(bodyObj.model).toEqual(model);
expect(bodyObj.prompt).toEqual(prompt);
expect(bodyObj.size).toEqual(size);
expect(bodyObj.output_format).toEqual(format);
expect(bodyObj.style).toEqual(style);
expect(bodyObj.quality).toEqual(quality);
expect(bodyObj.n).toEqual(1);
if (model !== "gpt-image-1") {
expect(bodyObj.response_format).toEqual('b64_json');
} else {
expect(bodyObj.response_format).toEqual(undefined);
}
};
/**
* API リクエストでエラー
*/
test('Fail to request', () => {
prepareConfigs('invalidKey', '', 'dall-e-2', 'Prompt', '512x512', '', '', '', 'test.png', null);
httpClient.setRequestHandler((request) => {
assertRequest(request, 'invalidKey', '', 'dall-e-2', 'Prompt', '512x512', undefined, undefined, undefined);
return httpClient.createHttpResponse(400, 'application/json', '{}');
});
assertError('Failed to request. status: 400');
});
/**
* API のレスポンスボディを作成
* @param {String} image 画像データ。本来はバイナリだが、テキストデータでテスト。
* @returns {String} response
*/
const createResponse = (image) => {
const responseObj = {
"created": Math.floor(Date.now() / 1000),
"data": [{
b64_json: base64.encodeToString(image)
}]
};
return JSON.stringify(responseObj);
};
/**
* ファイルのテスト
* @param file
* @param name
* @param contentType
* @param body
*/
const assertFile = (file, name, contentType, body) => {
expect(file.getName()).toEqual(name);
expect(file.getContentType()).toEqual(contentType);
const text = fileRepository.readFile(file, "UTF-8");
expect(text).toEqual(body);
};
/**
* 成功
*/
test('Success to request', () => {
const fileDef = prepareConfigs('key', '', 'dall-e-2', 'Prompt', '512x512', '', '', '', 'test.png', null);
httpClient.setRequestHandler(request => {
assertRequest(request, 'key', '', 'dall-e-2', 'Prompt', '512x512', undefined, undefined, undefined);
return httpClient.createHttpResponse(200, 'application/json', createResponse("image"));
});
main();
// データ項目の値をチェック
const files = engine.findData(fileDef);
expect(files.size()).toEqual(1);
assertFile(files.get(0), 'test.png', 'image/png', 'image');
});
/**
* 成功 - 組織 ID / スタイル / 品質を指定
* 生成された画像を保存するデータ項目に、他のファイルがすでに添付されている場合
*/
test('Success to request - with organization ID, Style, Quality', () => {
const fileDef = prepareConfigs('key2', 'org', 'dall-e-3', '綺麗な画像', '1024x1024', '', 'vivid', 'hd', 'image.png', null);
// 生成された画像を保存するデータ項目に、他のファイルをあらかじめ添付しておく
engine.setData(fileDef, [engine.createQfile('既存のファイル.json', 'image/png', '{}')]);
httpClient.setRequestHandler(request => {
assertRequest(request, 'key2', 'org', 'dall-e-3', '綺麗な画像', '1024x1024', undefined, 'vivid', 'hd');
return httpClient.createHttpResponse(200, 'application/json', createResponse("png"));
});
main();
// データ項目の値をチェック
const files = engine.findData(fileDef);
expect(files.size()).toEqual(2);
assertFile(files.get(0), '既存のファイル.json', 'image/png', '{}');
assertFile(files.get(1), 'image.png', 'image/png', 'png');
});
/**
* 成功 - サイズ / 画像形式 / 品質を指定
* gpt-image-1
*/
test('Success to request - Size, Format, Quality', () => {
const fileDef = prepareConfigs('key', '', 'gpt-image-1', 'Prompt', '1024x1792', 'webp', '', 'high', 'test.webp', null);
httpClient.setRequestHandler(request => {
assertRequest(request, 'key', '', 'gpt-image-1', 'Prompt', '1024x1792', 'webp', undefined, 'high');
return httpClient.createHttpResponse(200, 'application/json', createResponse("image"));
});
main();
// データ項目の値をチェック
const files = engine.findData(fileDef);
expect(files.size()).toEqual(1);
assertFile(files.get(0), 'test.webp', 'image/webp', 'image');
});
]]>