client icon indicating copy to clipboard operation
client copied to clipboard

Images Model Support (gpt-image-1)

Open gabrielrbarbosa opened this issue 8 months ago • 10 comments

https://github.com/openai/openai-python/commit/74d7692e94c9dca96db8793809d75631c22dbb87 https://platform.openai.com/docs/guides/images-vision?api-mode=responses

Example: Use new 'gpt-image-1' to generate and edit images or variations

gabrielrbarbosa avatar Apr 25 '25 05:04 gabrielrbarbosa

Are you saying our existing Images Create endpoint with the new model gpt-image-1 doesn't work?

$response = $client->images()->create([
    'model' => 'dall-e-3',
    'prompt' => 'A cute baby sea otter',
    'n' => 1,
    'size' => '1024x1024',
    'response_format' => 'url',
]);

iBotPeaches avatar Apr 25 '25 10:04 iBotPeaches

It doesn't work for me;

                        $result = $client->images()->edit([
                            'model' => 'gpt-image-1',
                            'image' => $this->prepareImageFiles(),
                            'prompt' => $prompt,
                            'size' => '1024x1024',
                            'quality' => 'high',
                            'n' => 1,
                        ]);
    private function prepareImageFiles(array $imageFiles): array
    {
        $images = [];
        
        if (count($imageFiles) > 0) {
            foreach ($imageFiles as $imagePath) {
                if (file_exists($imagePath)) {
                    try {
                        // Create a CURLFile object which is what the OpenAI PHP client expects
                        $images[] = new \CURLFile($imagePath, 'image/png',
                            basename($imagePath));
                    } catch (Exception $e) {
                        $this->logger->warning('Error processing image file: ' . $e->getMessage(),
                            [
                                'exception' => $e,
                                'file' => $imagePath
                            ]);
                    }
                } else {
                    $this->logger->warning('Image file does not exist: ' . $imagePath);
                }
            }
        }

        return $images;
    }

When running, I get;

[2025-04-25T13:39:08.894461+00:00] .ERROR: Error generating image: First argument to "Http\Message\MultipartStream\MultipartStreamBuilder::createStream()" must be a string, resource or StreamInterface. {"exception":"[object] (InvalidArgumentException(code: 0): First argument to \"Http\\Message\\MultipartStream\\MultipartStreamBuilder::createStream()\" must be a string, resource or StreamInterface. at /data/vendor/php-http/multipart-stream-builder/src/MultipartStreamBuilder.php:345)"} []

peterjaap avatar Apr 25 '25 13:04 peterjaap

Okay, I haven't messed with these endpoints yet. Let me finish Response API and I'll take some code samples here and dig into it.

iBotPeaches avatar Apr 25 '25 13:04 iBotPeaches

Also, the response_format doesn't exist for this model;

[message] => Unknown parameter: 'response_format'.

We also need to explicitly tell OpenAI the mime type when creating the CURLFile object, otherwise you'll get:

[message] => Invalid file 'image[0]': unsupported mimetype ('application/octet-stream'). Supported file formats are 'image/jpeg', 'image/png', and 'image/webp'

peterjaap avatar Apr 25 '25 13:04 peterjaap

Working test script;

<?php

$prompt_combine = "Combine the images to show the cat wearing the hat while being perched in a tree, still in pixel-art style.";
$output_dir = "."; // Replace with actual output directory
$cat_image_path = $output_dir . "image1.jpg"; // Assume exists
$hat_image_path = $output_dir . "image2"; // Assume exists

$api_key = "";
$edit_url = "https://api.openai.com/v1/images/edits";

try {
    // Open the image files for reading
    if (!file_exists($cat_image_path) || !file_exists($hat_image_path)) {
        throw new Exception("Error: Input image file(s) not found.");
    }

    // Prepare the POST data
    $data = [
        'model' => 'gpt-image-1',
        'prompt' => $prompt_combine,
        'size' => '1024x1536',
        'n' => 1
    ];

    // Initialize cURL
    $ch = curl_init();

    // Prepare the POST fields with file uploads
    $post_fields = [
        'image[0]' => new CURLFile($cat_image_path, 'image/jpeg'),
        'image[1]' => new CURLFile($hat_image_path, 'image/jpeg'),
        'model' => $data['model'],
        'prompt' => $data['prompt'],
        'size' => $data['size'],
        'n' => $data['n']
    ];

    // Set the cURL options
    curl_setopt($ch, CURLOPT_URL, $edit_url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . $api_key
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);

    // Execute the request and get the response
    $response = curl_exec($ch);

    // Check for errors
    if (curl_errno($ch)) {
        throw new Exception('Error during image combination/edit: ' . curl_error($ch));
    }

    // Close the cURL session
    curl_close($ch);

    // Process the response (assuming it's base64-encoded JSON)
    $response_data = json_decode($response, true);
print_r($response_data);
    if (isset($response_data['data'][0]['b64_json'])) {
        $image_b64 = $response_data['data'][0]['b64_json'];
        $output_path = $output_dir . "/cat_with_hat.jpeg";

        // Function to process base64 to image file (this is your equivalent of `process_b64_json`)
        file_put_contents($output_path, base64_decode($image_b64));
        echo "Image saved to: " . $output_path;
    } else {
        throw new Exception("Error: Response does not contain base64 image data.");
    }

} catch (Exception $e) {
    echo $e->getMessage();
}

peterjaap avatar Apr 25 '25 13:04 peterjaap

Ok I fixed my issue. Instead of using CURLFile, I just use $fileResource = fopen($imagePath, 'r'); and that works.

peterjaap avatar Apr 25 '25 14:04 peterjaap

Sorry, turns out it was two things:

Unknown parameter: 'response_format'.

"Your organization must be verified" Please go to: https://platform.openai.com/settings/organization/general

gabrielrbarbosa avatar Apr 25 '25 14:04 gabrielrbarbosa

Okay, so let me recap to see if I'm following.

  1. If you don't format the image in a specific format (resource?) - it crashes with an odd issue (response_format).
  2. If your Organization hasn't been verified - you can't use the new gpt-image-1 over API and thus it crashes and that error is not captured.

Am I missing anything?

iBotPeaches avatar Apr 25 '25 15:04 iBotPeaches

Actually using gpt-image-1 doesnt allow field response_format in img create, because it will always return base64

gabrielrbarbosa avatar Apr 25 '25 16:04 gabrielrbarbosa

Actually using gpt-image-1 doesnt allow field response_format in img create, because it will always return base64

Please check the API ref response_format string or null Optional Defaults to url The format in which generated images with dall-e-2 and dall-e-3 are returned. Must be one of url or b64_json. URLs are only valid for 60 minutes after the image has been generated. This parameter isn't supported for gpt-image-1 which will always return base64-encoded images. Source: https://platform.openai.com/docs/api-reference/images/create#images-create-response_format

A more clear examples for using gpt-image-1 https://cookbook.openai.com/examples/generate_images_with_gpt_image

momostafa avatar Apr 25 '25 16:04 momostafa

Okay I started with this sample.

        $response = OpenAI::images()->create([
            'model' => 'gpt-image-1',
            'prompt' => 'A cute baby sea otter',
            'size' => '1024x1024',
        ]);

and it error-ed out.

  "error": {
    "message": "Your organization must be verified to use the model `gpt-image-1`. Please go to: https://platform.openai.com/settings/organization/general and click on Verify Organization. If you just verified, it can take up to 15 minutes for access to propagate.",
    "type": "invalid_request_error",
    "param": null,
    "code": null
  }

I am awaiting verification of my org - then I will resume this investigation.

iBotPeaches avatar Apr 26 '25 13:04 iBotPeaches

I confim that once you're verified, the model works fine.

doc- avatar Apr 28 '25 07:04 doc-

It works with the old endpoints but the new ones are missing: images()->generations(), images()->edits() and images()->variations() : https://platform.openai.com/docs/api-reference/images

doc- avatar Apr 28 '25 08:04 doc-

Confirmed my sample works with a verified org.

  • images/generations - https://github.com/openai-php/client/blob/main/src/Resources/Images.php#L27
  • image/edits - https://github.com/openai-php/client/blob/main/src/Resources/Images.php#L44
  • image/variations - https://github.com/openai-php/client/blob/main/src/Resources/Images.php#L61

So I'm confused what we are missing.

iBotPeaches avatar Apr 28 '25 11:04 iBotPeaches

Oops, my bad. I mismatched it with my own implementation.

doc- avatar Apr 28 '25 11:04 doc-

No worries! I believe we've confirmed every thing in this thread is already supported. We had some issues with verified orgs, wrong parameters and wrong format for images - but all have since been fixed.

Closing for now.

iBotPeaches avatar Apr 28 '25 12:04 iBotPeaches

The new API returns usage data that is not being currently parsed: https://platform.openai.com/docs/api-reference/images

EDIT: Created a PR: https://github.com/openai-php/client/pull/571

abikali avatar Apr 30 '25 00:04 abikali