Skip to content

Commit

Permalink
Merge pull request #9 from flashvayne/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
flashvayne authored Mar 23, 2023
2 parents 4d2299d + 6661469 commit 77d5cf6
Show file tree
Hide file tree
Showing 13 changed files with 235 additions and 36 deletions.
62 changes: 39 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,37 @@
[中文版文档](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.
```pom
<dependency>
<groupId>io.github.flashvayne</groupId>
<artifactId>chatgpt-spring-boot-starter</artifactId>
<version>1.0.2</version>
<version>1.0.3</version>
</dependency>
```
### 2.Set chatgpt properties in your application.yml

```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;
Expand All @@ -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;
Expand All @@ -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<String> 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)
Expand Down
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>io.github.flashvayne</groupId>
<artifactId>chatgpt-spring-boot-starter</artifactId>
<version>1.0.2</version>
<version>1.0.3</version>

<name>chatgpt-spring-boot-starter</name>
<description>a starter to use chatgpt in springboot project easily</description>
Expand Down Expand Up @@ -58,7 +58,7 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
<version>1.18.24</version>
<version>1.18.26</version>
</dependency>

</dependencies>
Expand All @@ -79,7 +79,7 @@
<!-- <plugin>-->
<!-- <groupId>org.sonatype.plugins</groupId>-->
<!-- <artifactId>nexus-staging-maven-plugin</artifactId>-->
<!-- <version>1.6.7</version>-->
<!-- <version>1.6.13</version>-->
<!-- <extensions>true</extensions>-->
<!-- <configuration>-->
<!-- <serverId>ossrh</serverId>-->
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}

}
Original file line number Diff line number Diff line change
@@ -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 <a href="https://platform.openai.com/docs/api-reference/images/create">Create image</a>
*/
@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;

}
Original file line number Diff line number Diff line change
@@ -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<ImageData> data;

}
Original file line number Diff line number Diff line change
@@ -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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -17,4 +21,22 @@ public interface ChatgptService {
String multiChat(List<MultiChatMessage> 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<String> imageGenerate(String prompt, Integer n, ImageSize size, ImageFormat format);

ImageResponse imageGenerateRequest(ImageRequest imageRequest);

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -16,6 +17,7 @@
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;


Expand All @@ -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();
Expand All @@ -54,8 +55,7 @@ public ChatResponse sendChatRequest(ChatRequest chatRequest) {

@Override
public String multiChat(List<MultiChatMessage> 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();
Expand All @@ -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<String> 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<String> 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 <T> HttpEntity<?> buildHttpEntity(T request) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/json; charset=UTF-8"));
Expand Down
Loading

0 comments on commit 77d5cf6

Please sign in to comment.