openai-node
openai-node copied to clipboard
openai-node v3.2.1 createImageEdit() endpoint stopped working
Describe the bug
I've been using openai-node v3.1.0 and openai.createImageEdit() worked well.
I updated to the v3.2.1 to support the createChatCompletion() method, however my createImageEdit() is not working anymore. I get Error: Request failed with status code 400. If i downgrade to 3.1.0 is starts working back. Has createImageEdit() been changed in the latest update, so my call does not satisfy the new api? will add a code snippet wtih my method which works in v3.1.0 but doesn't in v3.2.1

To Reproduce
- update from v3.1.0 to v.3.2.1
- call createImageEdit (implementation provided in snippets section)
Code snippets
app.post('/inpaint', async (req, res) => {
const base64Image = req.body.image.split(';base64,').pop();
const path = `img-${uuidv4()}.png`;
fs.writeFile(path, base64Image, {encoding: 'base64'}, async function(err) {
const response = await openai.createImageEdit(
// We send the same image as a base and as a mask
fs.createReadStream(path),
fs.createReadStream(path),
req.body.prompt,
1,
'1024x1024'
);
fs.unlink(path, () => {
console.log(`Deleted file ${path}`)
});
// Download & proxy image to mitigate CORS
const imgPath = `static/${uuidv4()}.png`;
await axios({
method: 'get',
url: response.data.data[0].url,
responseType: 'arraybuffer',
}).then(response => {
fs.writeFileSync(imgPath, response.data);
});
res.json(`/${imgPath}`)
});
})
OS
macOS
Node version
v18.7.0
Library version
3.2.1
Is there any work around?
Is there any work around? I thought I could import 2 sdk versions and call methods from both. Asked ChatGpt about this, here's the answer: Technically, it is possible to import two versions of the same dependency in Node.js using the package management system like NPM. However, calling API methods from both versions of the SDK would be challenging, since each version of the SDK would have different function signatures and potentially use different interfaces to communicate with the API.
Moreover, importing multiple versions of the same dependency can cause conflicts and issues, leading to unexpected behavior in your application. It could result in memory leaks, name clashes, and other unwanted results.
Therefore, it is generally not recommended to import multiple versions of the same dependency unless you have a specific and well-thought-out reason to do so. In most cases, it is better to choose a single version of the dependency and use it consistently throughout your application. This ensures that there is no unexpected behavior, and it simplifies the maintenance of your codebase.
Please let me know if you find a solution
This API has a break change: https://github.com/openai/openai-openapi/commit/5b2ca2802bbe07c128d9ec1c4a6f9f5b3766201b#diff-d910ba2ef878f7db0223a966b81c8b3f3b65027bb39e4431bb05140171eece39L2269 https://github.com/openai/openai-node/commit/75f685369dd82be07a13d12828b6128669ee45b8#diff-216c63c6346d7d78fcd3b1ceeae8c9772b30f8fb2d43b8beabcda6ebd6aa6660R2239
Where mask will now be an optional parameter and moved to the third param. So you need to switch the params' position like:
const response = await openai.createImageEdit(
fs.createReadStream(path),
req.body.prompt,
// We send the same image as a base and as a mask
fs.createReadStream(path),
1,
'1024x1024'
);
This API has a break change: openai/openai-openapi@5b2ca28#diff-d910ba2ef878f7db0223a966b81c8b3f3b65027bb39e4431bb05140171eece39L2269 75f6853#diff-216c63c6346d7d78fcd3b1ceeae8c9772b30f8fb2d43b8beabcda6ebd6aa6660R2239
Where mask will now be an optional parameter and moved to the third param. So you need to switch the params' position like:
const response = await openai.createImageEdit( fs.createReadStream(path), req.body.prompt, // We send the same image as a base and as a mask fs.createReadStream(path), 1, '1024x1024' );
I tried it, and still getting error 400.
For anyone looking a workaround on this issue, try using axios and create the form to make a request to the endpoint itself instead of using the openai api which seems to be broken in the latest version, ie 3.2.1 Have been fighting with the api itself for a couple of hours until I found this issue open and decided to try to make the request myself...
Import dependencies
import fs from 'fs';
import FormData from 'form-data';
import axios from 'axios';
const form = new FormData();
form.append('image', await fs.createReadStream(`${originalImageFile}`), {
filename: originalImageFileName,
contentType: 'image/png',
});
form.append('mask', await fs.createReadStream(`${maskedImageFile}`), {
filename: maskedImageFileName,
contentType: 'image/png',
});
form.append('prompt', prompt);
form.append('n', '1');
form.append('size', size);
form.append('response_format', 'url');
const response = await axios.post<{ data: any }>(
`https://api.openai.com/v1/images/edits`,
form,
{
headers: {
...form.getHeaders(),
'Authorization': `Bearer ${apiKey}`,
},
},
);
Cheers
thanks for trick @repollo but i see an error : Error: Request failed with status code 400
me too
For those who encounter issue with typescript type vary bad 400 response. You probably do not have "square" image in your call.
You must provide SQUARE image.
This is 3.1.0
async function editImage(prompt: string, base: string, mask: string) {
const response = await openai.createImageEdit(
fs.createReadStream(base) as any,
fs.createReadStream(mask) as any,
prompt,
1,
"1024x1024"
);
const imageUrls = (response.data.data as any)
.map((image: any) => image.url)
.filter((url: any) => url !== null) as string[];
await downloadImages(imageUrls);
}
This is 3.2.0
async function editImage(prompt: string, base: string, mask: string) {
const response = await openai.createImageEdit(
fs.createReadStream(base) as any,
prompt,
fs.createReadStream(mask) as any,
1,
"1024x1024"
);
const imageUrls = (response.data.data as any)
.map((image: any) => image.url)
.filter((url: any) => url !== null) as string[];
await downloadImages(imageUrls);
}
Both worked