Add image generation, editing, and variations (#63)
https://beta.openai.com/docs/api-reference/images
This commit is contained in:
parent
3f8f02f104
commit
e68a098b87
|
@ -6,7 +6,7 @@ import lombok.Data;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An object describing an fine-tuned model. Returned by multiple fine-tune requests.
|
||||
* An object describing a fine-tuned model. Returned by multiple fine-tune requests.
|
||||
*
|
||||
* https://beta.openai.com/docs/api-reference/fine-tunes
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package com.theokanning.openai.image;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* A request for OpenAi to edit an image based on a prompt
|
||||
* All fields except prompt are optional
|
||||
*
|
||||
* https://beta.openai.com/docs/api-reference/images/create-edit
|
||||
*/
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class CreateImageEditRequest {
|
||||
|
||||
/**
|
||||
* A text description of the desired image(s). The maximum length in 1000 characters.
|
||||
*/
|
||||
@NonNull
|
||||
String prompt;
|
||||
|
||||
/**
|
||||
* The number of images to generate. Must be between 1 and 10. Defaults to 1.
|
||||
*/
|
||||
Integer n;
|
||||
|
||||
/**
|
||||
* The size of the generated images. Must be one of "256x256", "512x512", or "1024x1024". Defaults to "1024x1024".
|
||||
*/
|
||||
String size;
|
||||
|
||||
/**
|
||||
* The format in which the generated images are returned. Must be one of url or b64_json. Defaults to url.
|
||||
*/
|
||||
String responseFormat;
|
||||
|
||||
/**
|
||||
* A unique identifier representing your end-user, which will help OpenAI to monitor and detect abuse.
|
||||
*/
|
||||
String user;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.theokanning.openai.image;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* A request for OpenAi to create an image based on a prompt
|
||||
* All fields except prompt are optional
|
||||
*
|
||||
* https://beta.openai.com/docs/api-reference/images/create
|
||||
*/
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class CreateImageRequest {
|
||||
|
||||
/**
|
||||
* A text description of the desired image(s). The maximum length in 1000 characters.
|
||||
*/
|
||||
@NonNull
|
||||
String prompt;
|
||||
|
||||
/**
|
||||
* The number of images to generate. Must be between 1 and 10. Defaults to 1.
|
||||
*/
|
||||
Integer n;
|
||||
|
||||
/**
|
||||
* The size of the generated images. Must be one of "256x256", "512x512", or "1024x1024". Defaults to "1024x1024".
|
||||
*/
|
||||
String size;
|
||||
|
||||
/**
|
||||
* The format in which the generated images are returned. Must be one of url or b64_json. Defaults to url.
|
||||
*/
|
||||
String responseFormat;
|
||||
|
||||
/**
|
||||
* A unique identifier representing your end-user, which will help OpenAI to monitor and detect abuse.
|
||||
*/
|
||||
String user;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.theokanning.openai.image;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* A request for OpenAi to create a variation of an image
|
||||
* All fields are optional
|
||||
*
|
||||
* https://beta.openai.com/docs/api-reference/images/create-variation
|
||||
*/
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class CreateImageVariationRequest {
|
||||
|
||||
/**
|
||||
* The number of images to generate. Must be between 1 and 10. Defaults to 1.
|
||||
*/
|
||||
Integer n;
|
||||
|
||||
/**
|
||||
* The size of the generated images. Must be one of "256x256", "512x512", or "1024x1024". Defaults to "1024x1024".
|
||||
*/
|
||||
String size;
|
||||
|
||||
/**
|
||||
* The format in which the generated images are returned. Must be one of url or b64_json. Defaults to url.
|
||||
*/
|
||||
String responseFormat;
|
||||
|
||||
/**
|
||||
* A unique identifier representing your end-user, which will help OpenAI to monitor and detect abuse.
|
||||
*/
|
||||
String user;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.theokanning.openai.image;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* An object containing either a URL or a base 64 encoded image.
|
||||
*
|
||||
* https://beta.openai.com/docs/api-reference/images
|
||||
*/
|
||||
@Data
|
||||
public class Image {
|
||||
/**
|
||||
* The URL where the image can be accessed.
|
||||
*/
|
||||
String url;
|
||||
|
||||
|
||||
/**
|
||||
* Base64 encoded image string.
|
||||
*/
|
||||
@JsonProperty("b64_json")
|
||||
String b64Json;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.theokanning.openai.image;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An object with a list of image results.
|
||||
*
|
||||
* https://beta.openai.com/docs/api-reference/images
|
||||
*/
|
||||
@Data
|
||||
public class ImageResult {
|
||||
|
||||
/**
|
||||
* The creation time in epoch seconds.
|
||||
*/
|
||||
Long createdAt;
|
||||
|
||||
/**
|
||||
* List of image results.
|
||||
*/
|
||||
List<Image> data;
|
||||
}
|
|
@ -11,6 +11,9 @@ import com.theokanning.openai.file.File;
|
|||
import com.theokanning.openai.finetune.FineTuneEvent;
|
||||
import com.theokanning.openai.finetune.FineTuneRequest;
|
||||
import com.theokanning.openai.finetune.FineTuneResult;
|
||||
import com.theokanning.openai.image.CreateImageEditRequest;
|
||||
import com.theokanning.openai.image.CreateImageRequest;
|
||||
import com.theokanning.openai.image.ImageResult;
|
||||
import com.theokanning.openai.model.Model;
|
||||
import com.theokanning.openai.moderation.ModerationRequest;
|
||||
import com.theokanning.openai.moderation.ModerationResult;
|
||||
|
@ -82,6 +85,15 @@ public interface OpenAiApi {
|
|||
@DELETE("/v1/models/{fine_tune_id}")
|
||||
Single<DeleteResult> deleteFineTune(@Path("fine_tune_id") String fineTuneId);
|
||||
|
||||
@POST("/v1/images/generations")
|
||||
Single<ImageResult> createImage(@Body CreateImageRequest request);
|
||||
|
||||
@POST("/v1/images/edits")
|
||||
Single<ImageResult> createImageEdit(@Body RequestBody requestBody);
|
||||
|
||||
@POST("/v1/images/variations")
|
||||
Single<ImageResult> createImageVariation(@Body RequestBody requestBody);
|
||||
|
||||
@POST("/v1/moderations")
|
||||
Single<ModerationResult> createModeration(@Body ModerationRequest request);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.theokanning.openai.file.File;
|
|||
import com.theokanning.openai.finetune.FineTuneEvent;
|
||||
import com.theokanning.openai.finetune.FineTuneRequest;
|
||||
import com.theokanning.openai.finetune.FineTuneResult;
|
||||
import com.theokanning.openai.image.*;
|
||||
import com.theokanning.openai.model.Model;
|
||||
import com.theokanning.openai.moderation.ModerationRequest;
|
||||
import com.theokanning.openai.moderation.ModerationResult;
|
||||
|
@ -169,6 +170,62 @@ public class OpenAiService {
|
|||
return api.deleteFineTune(fineTuneId).blockingGet();
|
||||
}
|
||||
|
||||
public ImageResult createImage(CreateImageRequest request) {
|
||||
return api.createImage(request).blockingGet();
|
||||
}
|
||||
|
||||
public ImageResult createImageEdit(CreateImageEditRequest request, String imagePath, String maskPath) {
|
||||
java.io.File image = new java.io.File(imagePath);
|
||||
java.io.File mask = null;
|
||||
if (maskPath != null) {
|
||||
mask = new java.io.File(maskPath);
|
||||
}
|
||||
return createImageEdit(request, image, mask);
|
||||
}
|
||||
|
||||
public ImageResult createImageEdit(CreateImageEditRequest request, java.io.File image, java.io.File mask) {
|
||||
RequestBody imageBody = RequestBody.create(MediaType.parse("image"), image);
|
||||
|
||||
MultipartBody.Builder builder = new MultipartBody.Builder()
|
||||
.setType(MediaType.get("multipart/form-data"))
|
||||
.addFormDataPart("prompt", request.getPrompt())
|
||||
.addFormDataPart("size", request.getSize())
|
||||
.addFormDataPart("response_format", request.getResponseFormat())
|
||||
.addFormDataPart("image", "image", imageBody);
|
||||
|
||||
if (request.getN() != null) {
|
||||
builder.addFormDataPart("n", request.getN().toString());
|
||||
}
|
||||
|
||||
if (mask != null) {
|
||||
RequestBody maskBody = RequestBody.create(MediaType.parse("image"), mask);
|
||||
builder.addFormDataPart("mask", "mask", maskBody);
|
||||
}
|
||||
|
||||
return api.createImageEdit(builder.build()).blockingGet();
|
||||
}
|
||||
|
||||
public ImageResult createImageVariation(CreateImageVariationRequest request, String imagePath) {
|
||||
java.io.File image = new java.io.File(imagePath);
|
||||
return createImageVariation(request, image);
|
||||
}
|
||||
|
||||
public ImageResult createImageVariation(CreateImageVariationRequest request, java.io.File image) {
|
||||
RequestBody imageBody = RequestBody.create(MediaType.parse("image"), image);
|
||||
|
||||
MultipartBody.Builder builder = new MultipartBody.Builder()
|
||||
.setType(MediaType.get("multipart/form-data"))
|
||||
.addFormDataPart("size", request.getSize())
|
||||
.addFormDataPart("response_format", request.getResponseFormat())
|
||||
.addFormDataPart("image", "image", imageBody);
|
||||
|
||||
if (request.getN() != null) {
|
||||
builder.addFormDataPart("n", request.getN().toString());
|
||||
}
|
||||
|
||||
return api.createImageVariation(builder.build()).blockingGet();
|
||||
}
|
||||
|
||||
public ModerationResult createModeration(ModerationRequest request) {
|
||||
return api.createModeration(request).blockingGet();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package com.theokanning.openai;
|
||||
|
||||
import com.theokanning.openai.image.CreateImageEditRequest;
|
||||
import com.theokanning.openai.image.CreateImageRequest;
|
||||
import com.theokanning.openai.image.CreateImageVariationRequest;
|
||||
import com.theokanning.openai.image.Image;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
|
||||
public class ImageTest {
|
||||
|
||||
static String filePath = "src/test/resources/penguin.png";
|
||||
static String fileWithAlphaPath = "src/test/resources/penguin_with_alpha.png";
|
||||
static String maskPath = "src/test/resources/mask.png";
|
||||
|
||||
String token = System.getenv("OPENAI_TOKEN");
|
||||
OpenAiService service = new OpenAiService(token, 30);
|
||||
|
||||
|
||||
@Test
|
||||
void createImageUrl() {
|
||||
CreateImageRequest createImageRequest = CreateImageRequest.builder()
|
||||
.prompt("penguin")
|
||||
.n(3)
|
||||
.size("256x256")
|
||||
.user("testing")
|
||||
.build();
|
||||
|
||||
List<Image> images = service.createImage(createImageRequest).getData();
|
||||
assertEquals(3, images.size());
|
||||
assertNotNull(images.get(0).getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createImageBase64() {
|
||||
CreateImageRequest createImageRequest = CreateImageRequest.builder()
|
||||
.prompt("penguin")
|
||||
.responseFormat("b64_json")
|
||||
.user("testing")
|
||||
.build();
|
||||
|
||||
List<Image> images = service.createImage(createImageRequest).getData();
|
||||
assertEquals(1, images.size());
|
||||
assertNotNull(images.get(0).getB64Json());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createImageEdit() {
|
||||
CreateImageEditRequest createImageRequest = CreateImageEditRequest.builder()
|
||||
.prompt("a penguin with a red background")
|
||||
.responseFormat("url")
|
||||
.size("256x256")
|
||||
.user("testing")
|
||||
.n(2)
|
||||
.build();
|
||||
|
||||
List<Image> images = service.createImageEdit(createImageRequest, fileWithAlphaPath, null).getData();
|
||||
assertEquals(2, images.size());
|
||||
assertNotNull(images.get(0).getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createImageEditWithMask() {
|
||||
CreateImageEditRequest createImageRequest = CreateImageEditRequest.builder()
|
||||
.prompt("a penguin with a red hat")
|
||||
.responseFormat("url")
|
||||
.size("256x256")
|
||||
.user("testing")
|
||||
.n(2)
|
||||
.build();
|
||||
|
||||
List<Image> images = service.createImageEdit(createImageRequest, filePath, maskPath).getData();
|
||||
assertEquals(2, images.size());
|
||||
assertNotNull(images.get(0).getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createImageVariation() {
|
||||
CreateImageVariationRequest createImageVariationRequest = CreateImageVariationRequest.builder()
|
||||
.responseFormat("url")
|
||||
.size("256x256")
|
||||
.user("testing")
|
||||
.n(2)
|
||||
.build();
|
||||
|
||||
List<Image> images = service.createImageVariation(createImageVariationRequest, filePath).getData();
|
||||
assertEquals(2, images.size());
|
||||
assertNotNull(images.get(0).getUrl());
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
Loading…
Reference in New Issue