diff --git a/README.md b/README.md
index 498036e..196c5e8 100644
--- a/README.md
+++ b/README.md
@@ -3,8 +3,15 @@
[中文版文档](https://vayne.cc/2022/12/17/chatgpt-spring-boot-starter)
# chatgpt-spring-boot-starter
-Use chatgpt in springboot project easily.
-This starter is based on Openai Official Apis.
+This starter is based on OpenAi Official Apis. You can use chatgpt in springboot project easily.
+## Functions:
++ Chat
+
+ You can chat with ChatGPT using many models. Also, multi message is supported, so you can take a series of messages (including the conversation history) as input , and get a response message.
+
++ Image generation
+
+ Given a prompt and get generated image(s).
## Usage
### 1.Add maven dependency.
@@ -12,7 +19,7 @@ This starter is based on Openai Official Apis.
io.github.flashvayne
chatgpt-spring-boot-starter
- 1.0.2
+ 1.0.3
```
### 2.Set chatgpt properties in your application.yml
@@ -20,21 +27,13 @@ This starter is based on Openai Official Apis.
```yml
chatgpt:
api-key: xxxxxxxxxxx #api-key. It can be generated here https://platform.openai.com/account/api-keys
-# some properties as below have default values. For descriptions of these fields, please refer to https://platform.openai.com/docs/api-reference/completions/create and https://platform.openai.com/docs/api-reference/chat/create
-# url: https://api.openai.com/v1/completions
-# model: text-davinci-003
-# max-tokens: 500
- temperature: 1.0
-# top-p: 1.0
- multi:
-# url: https://api.openai.com/v1/chat/completions
-# model: gpt-3.5-turbo
-# max-tokens: 500
- temperature: 1.0
-# top-p: 1.0
+# some more properties(model,max-tokens...etc.) have default values. Also you can config them here.
```
-### 3.Inject bean ChatgptService anywhere you require it, and invoke its method to send message to chatgpt and get the response.
-#### 3.1 Single message
+### 3.Inject bean ChatgptService anywhere you require it, and invoke its methods.
+#### 3.1 Chat
+
+##### 3.1.1 Single message
+
```java
@Autowired
private ChatgptService chatgptService;
@@ -49,7 +48,7 @@ public void test2(){
System.out.print(responseMessage); //I'm doing well, thank you. How about you?
}
```
-#### 3.2 Multi message. You can take a series of messages (including the conversation history) as input , and return a response message as output.
+##### 3.1.2 Multi message. You can take a series of messages (including the conversation history) as input , and return a response message as output.
```java
@Autowired
private ChatgptService chatgptService;
@@ -64,12 +63,29 @@ public void testMultiChat(){
System.out.print(responseMessage); //The 2020 World Series was played at Globe Life Field in Arlington, Texas.
}
```
-Messages must be an array of message objects, where each object has a role (either "system", "user", or "assistant") and content (the content of the message). Conversations can be as short as 1 message or fill many pages.
++ Tips:
+ + Messages must be an array of message objects, where each object has a role (either "system", "user", or "assistant") and content (the content of the message). Conversations can be as short as 1 message or fill many pages.
+ + The system message helps set the behavior of the assistant. In the example above, the assistant was instructed with "You are a helpful assistant."
+ + The user messages help instruct the assistant. They can be generated by the end users of an application, or set by a developer as an instruction.
+ + The assistant messages help store prior responses. They can also be written by a developer to help give examples of desired behavior.
+ For more details, please refer to [chat format](https://platform.openai.com/docs/guides/chat/introduction)
+
-+ The system message helps set the behavior of the assistant. In the example above, the assistant was instructed with "You are a helpful assistant."
-+ The user messages help instruct the assistant. They can be generated by the end users of an application, or set by a developer as an instruction.
-+ The assistant messages help store prior responses. They can also be written by a developer to help give examples of desired behavior.
-For more details, please refer to [chat format](https://platform.openai.com/docs/guides/chat/introduction)
+#### 3.2 Image generation
+```java
+@Autowired
+private ChatgptService chatgptService;
+
+public void testImage(){
+ String imageUrl = chatgptService.imageGenerate("A cute baby sea otter");
+ System.out.print(imageUrl); //https://oaidalleapip.......
+}
+
+public void testImageList(){
+ List images = chatgptService.imageGenerate("A cute baby sea otter", 2, ImageSize.SMALL, ImageFormat.URL);
+ System.out.print(images.toString());//["https://oaidalleapipr.....ZwA%3D","https://oaidalleapipr....RE0%3D"]
+}
+```
## Demo project:
[demo-chatgpt-spring-boot-starter](https://github.com/flashvayne/demo-chatgpt-spring-boot-starter)
diff --git a/pom.xml b/pom.xml
index 809d8a2..68ddeba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
io.github.flashvayne
chatgpt-spring-boot-starter
- 1.0.2
+ 1.0.3
chatgpt-spring-boot-starter
a starter to use chatgpt in springboot project easily
@@ -58,7 +58,7 @@
org.projectlombok
lombok
provided
- 1.18.24
+ 1.18.26
@@ -79,7 +79,7 @@
-
+
diff --git a/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageData.java b/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageData.java
new file mode 100644
index 0000000..05b03e1
--- /dev/null
+++ b/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageData.java
@@ -0,0 +1,12 @@
+package io.github.flashvayne.chatgpt.dto.image;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class ImageData {
+ private String url;
+
+ @JsonProperty("b64_json")
+ private String b64Json;
+}
diff --git a/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageFormat.java b/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageFormat.java
new file mode 100644
index 0000000..984b5cb
--- /dev/null
+++ b/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageFormat.java
@@ -0,0 +1,17 @@
+package io.github.flashvayne.chatgpt.dto.image;
+
+public enum ImageFormat {
+
+ URL("url"),BASE64("b64_json");
+
+ private final String format;
+
+ ImageFormat(String format){
+ this.format = format;
+ }
+
+ public String getFormat(){
+ return format;
+ }
+
+}
diff --git a/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageRequest.java b/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageRequest.java
new file mode 100644
index 0000000..69c0ccb
--- /dev/null
+++ b/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageRequest.java
@@ -0,0 +1,28 @@
+package io.github.flashvayne.chatgpt.dto.image;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * ImageRequest is used to construct request body.
+ * For descriptions of all fields, please refer to Create image
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ImageRequest {
+
+ private String prompt;
+ private Integer n;
+ private String size;
+
+ @JsonProperty("response_format")
+ private String responseFormat;
+
+ private String user;
+
+}
diff --git a/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageResponse.java b/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageResponse.java
new file mode 100644
index 0000000..0af4448
--- /dev/null
+++ b/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageResponse.java
@@ -0,0 +1,18 @@
+package io.github.flashvayne.chatgpt.dto.image;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class ImageResponse {
+ private Date created;
+
+ private List data;
+
+}
diff --git a/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageSize.java b/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageSize.java
new file mode 100644
index 0000000..a1fd060
--- /dev/null
+++ b/src/main/java/io/github/flashvayne/chatgpt/dto/image/ImageSize.java
@@ -0,0 +1,17 @@
+package io.github.flashvayne.chatgpt.dto.image;
+
+public enum ImageSize {
+
+ SMALL("256x256"), MEDIUM("512x512"), LARGE("1024x1024");
+
+ private final String size;
+
+ ImageSize(String size) {
+ this.size = size;
+ }
+
+ public String getSize() {
+ return size;
+ }
+
+}
diff --git a/src/main/java/io/github/flashvayne/chatgpt/property/ChatgptProperties.java b/src/main/java/io/github/flashvayne/chatgpt/property/ChatgptProperties.java
index 750e01c..c5fff98 100644
--- a/src/main/java/io/github/flashvayne/chatgpt/property/ChatgptProperties.java
+++ b/src/main/java/io/github/flashvayne/chatgpt/property/ChatgptProperties.java
@@ -15,14 +15,17 @@ public class ChatgptProperties {
private Integer maxTokens = 500;
- private Double temperature = 0.0;
+ private Double temperature = 1.0;
private Double topP = 1.0;
private MultiChatProperties multi;
+ private ImageProperties image;
+
public ChatgptProperties() {
this.multi = new MultiChatProperties();
+ this.image = new ImageProperties();
}
public String getApiKey() {
@@ -80,4 +83,12 @@ public MultiChatProperties getMulti() {
public void setMulti(MultiChatProperties multi) {
this.multi = multi;
}
+
+ public ImageProperties getImage() {
+ return image;
+ }
+
+ public void setImage(ImageProperties image) {
+ this.image = image;
+ }
}
diff --git a/src/main/java/io/github/flashvayne/chatgpt/property/ImageProperties.java b/src/main/java/io/github/flashvayne/chatgpt/property/ImageProperties.java
new file mode 100644
index 0000000..3dc401b
--- /dev/null
+++ b/src/main/java/io/github/flashvayne/chatgpt/property/ImageProperties.java
@@ -0,0 +1,14 @@
+package io.github.flashvayne.chatgpt.property;
+
+public class ImageProperties {
+
+ private String url = "https://api.openai.com/v1/images/generations";
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+}
diff --git a/src/main/java/io/github/flashvayne/chatgpt/property/MultiChatProperties.java b/src/main/java/io/github/flashvayne/chatgpt/property/MultiChatProperties.java
index b541df7..6c24fe1 100644
--- a/src/main/java/io/github/flashvayne/chatgpt/property/MultiChatProperties.java
+++ b/src/main/java/io/github/flashvayne/chatgpt/property/MultiChatProperties.java
@@ -8,7 +8,7 @@ public class MultiChatProperties {
private Integer maxTokens = 500;
- private Double temperature = 0.0;
+ private Double temperature = 1.0;
private Double topP = 1.0;
diff --git a/src/main/java/io/github/flashvayne/chatgpt/service/ChatgptService.java b/src/main/java/io/github/flashvayne/chatgpt/service/ChatgptService.java
index 50c5c4b..6c67590 100644
--- a/src/main/java/io/github/flashvayne/chatgpt/service/ChatgptService.java
+++ b/src/main/java/io/github/flashvayne/chatgpt/service/ChatgptService.java
@@ -5,6 +5,10 @@
import io.github.flashvayne.chatgpt.dto.chat.MultiChatMessage;
import io.github.flashvayne.chatgpt.dto.chat.MultiChatRequest;
import io.github.flashvayne.chatgpt.dto.chat.MultiChatResponse;
+import io.github.flashvayne.chatgpt.dto.image.ImageFormat;
+import io.github.flashvayne.chatgpt.dto.image.ImageRequest;
+import io.github.flashvayne.chatgpt.dto.image.ImageResponse;
+import io.github.flashvayne.chatgpt.dto.image.ImageSize;
import java.util.List;
@@ -17,4 +21,22 @@ public interface ChatgptService {
String multiChat(List messages);
MultiChatResponse multiChatRequest(MultiChatRequest multiChatRequest);
+
+ /**
+ * @param prompt A text description of the desired image(s). The maximum length is 1000 characters.
+ * @return generated image url
+ */
+ String imageGenerate(String prompt);
+
+ /**
+ * @param prompt A text description of the desired image(s). The maximum length is 1000 characters.
+ * @param n The number of images to generate. Must be between 1 and 10.
+ * @param size The size of the generated images. Must be one of ImageFormat.SMALL("256x256"), ImageFormat.MEDIUM("512x512"), ImageFormat.LARGE("1024x1024").
+ * @param format The format in which the generated images are returned. Must be one of ImageFormat.URL("url"), ImageFormat.BASE64("b64_json").
+ * @return image url/base64 list
+ */
+ List imageGenerate(String prompt, Integer n, ImageSize size, ImageFormat format);
+
+ ImageResponse imageGenerateRequest(ImageRequest imageRequest);
+
}
diff --git a/src/main/java/io/github/flashvayne/chatgpt/service/impl/DefaultChatgptService.java b/src/main/java/io/github/flashvayne/chatgpt/service/impl/DefaultChatgptService.java
index 26fdd23..df4f95f 100644
--- a/src/main/java/io/github/flashvayne/chatgpt/service/impl/DefaultChatgptService.java
+++ b/src/main/java/io/github/flashvayne/chatgpt/service/impl/DefaultChatgptService.java
@@ -4,6 +4,7 @@
import io.github.flashvayne.chatgpt.dto.chat.MultiChatMessage;
import io.github.flashvayne.chatgpt.dto.chat.MultiChatRequest;
import io.github.flashvayne.chatgpt.dto.chat.MultiChatResponse;
+import io.github.flashvayne.chatgpt.dto.image.*;
import io.github.flashvayne.chatgpt.exception.ChatgptException;
import io.github.flashvayne.chatgpt.property.ChatgptProperties;
import io.github.flashvayne.chatgpt.dto.ChatResponse;
@@ -16,6 +17,7 @@
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
+import java.util.ArrayList;
import java.util.List;
@@ -36,8 +38,7 @@ public DefaultChatgptService(ChatgptProperties chatgptProperties) {
@Override
public String sendMessage(String message) {
- ChatRequest chatRequest = new ChatRequest(chatgptProperties.getModel(), message,
- chatgptProperties.getMaxTokens(), chatgptProperties.getTemperature(), chatgptProperties.getTopP());
+ ChatRequest chatRequest = new ChatRequest(chatgptProperties.getModel(), message, chatgptProperties.getMaxTokens(), chatgptProperties.getTemperature(), chatgptProperties.getTopP());
ChatResponse chatResponse = this.getResponse(this.buildHttpEntity(chatRequest), ChatResponse.class, chatgptProperties.getUrl());
try {
return chatResponse.getChoices().get(0).getText();
@@ -54,8 +55,7 @@ public ChatResponse sendChatRequest(ChatRequest chatRequest) {
@Override
public String multiChat(List messages) {
- MultiChatRequest multiChatRequest = new MultiChatRequest(chatgptProperties.getMulti().getModel(), messages,
- chatgptProperties.getMulti().getMaxTokens(), chatgptProperties.getMulti().getTemperature(), chatgptProperties.getMulti().getTopP());
+ MultiChatRequest multiChatRequest = new MultiChatRequest(chatgptProperties.getMulti().getModel(), messages, chatgptProperties.getMulti().getMaxTokens(), chatgptProperties.getMulti().getTemperature(), chatgptProperties.getMulti().getTopP());
MultiChatResponse multiChatResponse = this.getResponse(this.buildHttpEntity(multiChatRequest), MultiChatResponse.class, chatgptProperties.getMulti().getUrl());
try {
return multiChatResponse.getChoices().get(0).getMessage().getContent();
@@ -70,6 +70,43 @@ public MultiChatResponse multiChatRequest(MultiChatRequest multiChatRequest) {
return this.getResponse(this.buildHttpEntity(multiChatRequest), MultiChatResponse.class, chatgptProperties.getMulti().getUrl());
}
+ @Override
+ public String imageGenerate(String prompt) {
+ ImageRequest imageRequest = new ImageRequest(prompt, null, null, null, null);
+ ImageResponse imageResponse = this.getResponse(this.buildHttpEntity(imageRequest), ImageResponse.class, chatgptProperties.getImage().getUrl());
+ try {
+ return imageResponse.getData().get(0).getUrl();
+ } catch (Exception e) {
+ log.error("parse image url error", e);
+ throw e;
+ }
+ }
+
+ @Override
+ public List imageGenerate(String prompt, Integer n, ImageSize size, ImageFormat format) {
+ ImageRequest imageRequest = new ImageRequest(prompt, n, size.getSize(), format.getFormat(), null);
+ ImageResponse imageResponse = this.getResponse(this.buildHttpEntity(imageRequest), ImageResponse.class, chatgptProperties.getImage().getUrl());
+ try {
+ List list = new ArrayList<>();
+ imageResponse.getData().forEach(imageData -> {
+ if (format.equals(ImageFormat.URL)) {
+ list.add(imageData.getUrl());
+ } else {
+ list.add(imageData.getB64Json());
+ }
+ });
+ return list;
+ } catch (Exception e) {
+ log.error("parse image url error", e);
+ throw e;
+ }
+ }
+
+ @Override
+ public ImageResponse imageGenerateRequest(ImageRequest imageRequest) {
+ return this.getResponse(this.buildHttpEntity(imageRequest), ImageResponse.class, chatgptProperties.getImage().getUrl());
+ }
+
protected HttpEntity> buildHttpEntity(T request) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/json; charset=UTF-8"));
diff --git a/src/main/resources/META-INF/spring-configuration-metadata.json b/src/main/resources/META-INF/spring-configuration-metadata.json
index 2160487..d6e8ea5 100644
--- a/src/main/resources/META-INF/spring-configuration-metadata.json
+++ b/src/main/resources/META-INF/spring-configuration-metadata.json
@@ -12,7 +12,8 @@
"type": "java.lang.String",
"sourceType": "io.github.flashvayne.chatgpt.property.ChatgptProperties",
"defaultValue": "",
- "description": "apiKey of chatgpt. It can be generated in this link https://platform.openai.com/account/api-keys"
+ "description": "apiKey of chatgpt. It can be generated in this link https://platform.openai.com/account/api-keys",
+ "required": true
},
{
"name": "chatgpt.model",
@@ -38,7 +39,7 @@
"name": "chatgpt.temperature",
"type": "java.lang.Double",
"sourceType": "io.github.flashvayne.chatgpt.property.ChatgptProperties",
- "defaultValue": "0.0",
+ "defaultValue": "1.0",
"description": "What sampling temperature to use. Higher values means the model will take more risks. Try 0.9 for more creative applications, and 0 (argmax sampling) for ones with a well-defined answer.We generally recommend altering this or top_p but not both."
},{
"name": "chatgpt.top-p",
@@ -59,7 +60,7 @@
"name": "chatgpt.multi.url",
"type": "java.lang.String",
"sourceType": "io.github.flashvayne.chatgpt.property.MultiChatProperties",
- "defaultValue": "https://api.openai.com/v1/completions",
+ "defaultValue": "https://api.openai.com/v1/chat/completions",
"description": "The request url."
},
{
@@ -72,7 +73,7 @@
"name": "chatgpt.multi.temperature",
"type": "java.lang.Double",
"sourceType": "io.github.flashvayne.chatgpt.property.MultiChatProperties",
- "defaultValue": "0.0",
+ "defaultValue": "1.0",
"description": "What sampling temperature to use. Higher values means the model will take more risks. Try 0.9 for more creative applications, and 0 (argmax sampling) for ones with a well-defined answer.We generally recommend altering this or top_p but not both."
},{
"name": "chatgpt.multi.top-p",
@@ -80,6 +81,12 @@
"sourceType": "io.github.flashvayne.chatgpt.property.MultiChatProperties",
"defaultValue": "1.0",
"description": "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.We generally recommend altering this or temperature but not both."
+ },{
+ "name": "chatgpt.image.url",
+ "type": "java.lang.String",
+ "sourceType": "io.github.flashvayne.chatgpt.property.ImageProperties",
+ "defaultValue": "https://api.openai.com/v1/images/generations",
+ "description": "The request url."
}
],
"hints": []