(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'); }); ]]>