├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── com
│ └── jeffrey
│ └── chatgpt
│ ├── IOpenAiApi.java
│ ├── common
│ └── Constants.java
│ ├── domain
│ ├── billing
│ │ ├── BillingUsage.java
│ │ ├── DailyCost.java
│ │ ├── LineItem.java
│ │ ├── Plan.java
│ │ └── Subscription.java
│ ├── chat
│ │ ├── ChatChoice.java
│ │ ├── ChatCompletionRequest.java
│ │ ├── ChatCompletionResponse.java
│ │ └── Message.java
│ ├── edits
│ │ ├── EditRequest.java
│ │ └── EditResponse.java
│ ├── embedd
│ │ ├── EmbeddingRequest.java
│ │ ├── EmbeddingResponse.java
│ │ └── Item.java
│ ├── files
│ │ ├── DeleteFileResponse.java
│ │ ├── File.java
│ │ └── UploadFileResponse.java
│ ├── images
│ │ ├── ImageEditRequest.java
│ │ ├── ImageEnum.java
│ │ ├── ImageRequest.java
│ │ ├── ImageResponse.java
│ │ └── Item.java
│ ├── other
│ │ ├── Choice.java
│ │ ├── OpenAiResponse.java
│ │ └── Usage.java
│ ├── qa
│ │ ├── QAChoice.java
│ │ ├── QACompletionRequest.java
│ │ └── QACompletionResponse.java
│ └── whisper
│ │ ├── TranscriptionsRequest.java
│ │ ├── TranslationsRequest.java
│ │ ├── WhisperEnum.java
│ │ └── WhisperResponse.java
│ ├── interceptor
│ └── OpenAiInterceptor.java
│ └── session
│ ├── Configuration.java
│ ├── OpenAiSession.java
│ ├── OpenAiSessionFactory.java
│ └── defaults
│ ├── DefaultOpenAiSession.java
│ └── DefaultOpenAiSessionFactory.java
└── test
└── java
└── com
└── jeffrey
└── chatgpt
└── test
├── ApiTest.java
├── ClientTest.java
└── HttpClientTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | /chatgpt-sdk-java.iml
23 | /target/
24 | /.idea/
25 |
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Jeffrey You
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenAI_SDK
2 |
3 | ## About
4 | Provides an easy-to-use SDK for Java developers to interact with the APIs of open AI models.
5 |
6 | ## Features
7 | - Rapidly develop products based on the platform, improve development efficiency, and meet fast delivery requirements.
8 | - Concise and easy to understand, code specification requirements, can be used as enterprise code specification.
9 | - The steps to use are very simple, and one line of code realizes the required functions.
10 | - Support multiple proxy platforms, perfectly adapt to various APIs.
11 | - Dynamically expand Max Tokens according to the model
12 | - Rich pre-data verification to avoid direct contact with API
13 |
14 | ## Supported APIs List
15 | - Chat
16 | - Images
17 | - Files
18 | - Audio
19 | - Embeddings
20 | - Billing
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.jeffrey.chatgpt
8 | chatgpt-sdk-java
9 | 1.0-SNAPSHOT
10 |
11 | chatgpt-sdk-java
12 | OpenAI Java SDK, ChatGPT Java SDK
13 |
14 |
15 | 1.8
16 | UTF-8
17 | 1.8
18 | 1.8
19 | 2.9.0
20 | 2.0.6
21 |
22 |
23 |
24 |
25 | org.slf4j
26 | slf4j-api
27 | ${slf4j.version}
28 |
29 |
30 | org.slf4j
31 | slf4j-simple
32 | ${slf4j.version}
33 |
34 |
35 | com.fasterxml.jackson.core
36 | jackson-databind
37 | 2.13.3
38 |
39 |
40 | cn.hutool
41 | hutool-all
42 | 5.8.12
43 |
44 |
45 | com.squareup.okhttp3
46 | okhttp-sse
47 | 3.14.9
48 |
49 |
50 | com.squareup.okhttp3
51 | logging-interceptor
52 | 3.14.9
53 |
54 |
55 | com.squareup.retrofit2
56 | retrofit
57 | ${retrofit2.version}
58 |
59 |
60 | com.squareup.retrofit2
61 | converter-jackson
62 | ${retrofit2.version}
63 |
64 |
65 | com.squareup.retrofit2
66 | adapter-rxjava2
67 | ${retrofit2.version}
68 |
69 |
70 | junit
71 | junit
72 | 4.13.2
73 | test
74 |
75 |
76 | org.jetbrains
77 | annotations
78 | RELEASE
79 | compile
80 |
81 |
82 | com.knuddels
83 | jtokkit
84 | 0.2.0
85 |
86 |
87 | org.projectlombok
88 | lombok
89 | 1.18.24
90 | compile
91 |
92 |
93 |
94 |
95 | chatgpt-sdk-java
96 |
97 |
98 |
99 | org.apache.maven.plugins
100 | maven-surefire-plugin
101 | 2.12.4
102 |
103 | true
104 |
105 |
106 |
107 | org.apache.maven.plugins
108 | maven-compiler-plugin
109 |
110 | 8
111 | 8
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/IOpenAiApi.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt;
2 |
3 | import com.jeffrey.chatgpt.domain.chat.ChatCompletionRequest;
4 | import com.jeffrey.chatgpt.domain.chat.ChatCompletionResponse;
5 | import com.jeffrey.chatgpt.domain.qa.QACompletionRequest;
6 | import com.jeffrey.chatgpt.domain.qa.QACompletionResponse;
7 | import com.jeffrey.chatgpt.domain.billing.BillingUsage;
8 | import com.jeffrey.chatgpt.domain.billing.Subscription;
9 | import com.jeffrey.chatgpt.domain.edits.EditRequest;
10 | import com.jeffrey.chatgpt.domain.edits.EditResponse;
11 | import com.jeffrey.chatgpt.domain.embedd.EmbeddingRequest;
12 | import com.jeffrey.chatgpt.domain.embedd.EmbeddingResponse;
13 | import com.jeffrey.chatgpt.domain.files.DeleteFileResponse;
14 | import com.jeffrey.chatgpt.domain.files.UploadFileResponse;
15 | import com.jeffrey.chatgpt.domain.images.ImageRequest;
16 | import com.jeffrey.chatgpt.domain.images.ImageResponse;
17 | import com.jeffrey.chatgpt.domain.other.OpenAiResponse;
18 | import com.jeffrey.chatgpt.domain.whisper.WhisperResponse;
19 |
20 |
21 | import io.reactivex.Single;
22 | import okhttp3.MultipartBody;
23 | import okhttp3.RequestBody;
24 | import okhttp3.ResponseBody;
25 | import retrofit2.http.*;
26 |
27 |
28 | import java.io.File;
29 | import java.time.LocalDate;
30 | import java.util.Map;
31 |
32 | /**
33 | * @author Jeffrey You
34 | * @description ChatGPT API:https://platform.openai.com/playground
35 | */
36 | public interface IOpenAiApi {
37 | String v1_completions = "v1/completions";
38 | String v1_chat_completions = "v1/chat/completions";
39 |
40 |
41 | /**
42 | * Default GPT-3.5 Chat Model
43 | *
44 | * @param chatCompletionRequest Request Body
45 | * @return Return Result
46 | */
47 | @POST("v1/chat/completions")
48 | Single completions(@Body ChatCompletionRequest chatCompletionRequest);
49 |
50 | /**
51 | * Q & A Model
52 | *
53 | * @param qaCompletionRequest Request Body
54 | * @return Return Result
55 | */
56 | @POST("v1/completions")
57 | Single completions(@Body QACompletionRequest qaCompletionRequest);
58 |
59 |
60 |
61 | /**
62 | * Edit Text
63 | *
64 | * @param editRequest Request Body
65 | * @return Return Result
66 | */
67 | @POST("v1/edits")
68 | Single edits(@Body EditRequest editRequest);
69 |
70 | /**
71 | * Generate Picture
72 | *
73 | * @param imageRequest Request Body
74 | * @return Return Result
75 | */
76 | @POST("v1/images/generations")
77 | Single genImages(@Body ImageRequest imageRequest);
78 |
79 |
80 | /**
81 | * Modify Picture
82 | *
83 | * @param image The image to edit
84 | * @param mask Optional mask to apply to the image
85 | * @param requestBodyMap Request Body
86 | * @return Return Result
87 | */
88 | @Multipart
89 | @POST("v1/images/edits")
90 | Single editImages(@Part MultipartBody.Part image, @Part MultipartBody.Part mask, @PartMap Map requestBodyMap);
91 |
92 | /**
93 | * Embedding
94 | *
95 | * @param embeddingRequest Request Body
96 | * @return Return Result
97 | */
98 | @POST("v1/embeddings")
99 | Single embeddings(@Body EmbeddingRequest embeddingRequest);
100 |
101 | /**
102 | * Get Files
103 | * @return Return Result
104 | */
105 | @GET("v1/files")
106 | Single> files();
107 |
108 | /**
109 | * Upload File
110 | *
111 | * @param file file
112 | * @param purpose "fine-tune"
113 | * @return Return Result
114 | */
115 | @Multipart
116 | @POST("v1/files")
117 | Single uploadFile(@Part MultipartBody.Part file, @Part("purpose") RequestBody purpose);
118 |
119 | /**
120 | * Delete File
121 | *
122 | * @param fileId File ID
123 | * @return Return Result
124 | */
125 | @DELETE("v1/files/{file_id}")
126 | Single deleteFile(@Path("file_id") String fileId);
127 |
128 | /**
129 | * Search File
130 | *
131 | * @param fileId File ID
132 | * @return Return Result
133 | */
134 | @GET("v1/files/{file_id}")
135 | Single retrieveFile(@Path("file_id") String fileId);
136 |
137 | /**
138 | * Search File Content
139 | *
140 | * @param fileId File ID
141 | * @return Return Result
142 | */
143 | @Streaming
144 | @GET("v1/files/{file_id}/content")
145 | Single retrieveFileContent(@Path("file_id") String fileId);
146 |
147 | /**
148 | * Audio Transcription
149 | *
150 | * @param file Audio file
151 | * @param requestBodyMap Request Body
152 | * @return Return Result
153 | */
154 | @Multipart
155 | @POST("v1/audio/transcriptions")
156 | Single speed2TextTranscriptions(@Part MultipartBody.Part file, @PartMap() Map requestBodyMap);
157 |
158 | /**
159 | * Audio Translation
160 | *
161 | * @param file Audio file
162 | * @param requestBodyMap Request Body
163 | * @return Return Result
164 | */
165 | @Multipart
166 | @POST("v1/audio/translations")
167 | Single speed2TextTranslations(@Part MultipartBody.Part file, @PartMap() Map requestBodyMap);
168 |
169 | /**
170 | * Billing Subscription
171 | *
172 | * @return Return Result
173 | */
174 | @GET("v1/dashboard/billing/subscription")
175 | Single subscription();
176 |
177 | /**
178 | * Usage
179 | *
180 | * @param starDate Start Time
181 | * @param endDate End Time
182 | * @return Return Result
183 | */
184 | @GET("v1/dashboard/billing/usage")
185 | Single billingUsage(@Query("start_date") LocalDate starDate, @Query("end_date") LocalDate endDate);
186 |
187 |
188 | }
189 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/common/Constants.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.common;
2 |
3 | /**
4 | * @author Jeffrey You
5 | * @description Role Definition
6 | */
7 | public class Constants {
8 |
9 | public enum Role {
10 |
11 | SYSTEM("system"),
12 | USER("user"),
13 | ASSISTANT("assistant"),
14 | ;
15 |
16 | private String code;
17 |
18 | Role(String code) {
19 | this.code = code;
20 | }
21 |
22 | public String getCode() {
23 | return code;
24 | }
25 |
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/billing/BillingUsage.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.billing;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import lombok.Data;
5 |
6 | import java.math.BigDecimal;
7 | import java.util.List;
8 |
9 | /**
10 | * @author Jeffrey You
11 | * @description Billing Usage
12 | */
13 | @Data
14 | public class BillingUsage {
15 |
16 | @JsonProperty("object")
17 | private String object;
18 | @JsonProperty("daily_costs")
19 | private List dailyCosts;
20 | @JsonProperty("total_usage")
21 | private BigDecimal totalUsage;
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/billing/DailyCost.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.billing;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import lombok.Data;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * @author Jeffrey You
10 | * @description Daily Cost
11 | */
12 | @Data
13 | public class DailyCost {
14 | @JsonProperty("timestamp")
15 | private long timestamp;
16 | @JsonProperty("line_items")
17 | private List lineItems;
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/billing/LineItem.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.billing;
2 |
3 | import lombok.Data;
4 |
5 | import java.math.BigDecimal;
6 |
7 | /**
8 | * @author Jeffrey You
9 | * @description Billing
10 | */
11 | @Data
12 | public class LineItem {
13 | private String name;
14 | private BigDecimal cost;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/billing/Plan.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.billing;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @author Jeffrey You
7 | * @description Billing Plan
8 | */
9 | @Data
10 | public class Plan {
11 | private String title;
12 | private String id;
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/billing/Subscription.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.billing;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import lombok.Data;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * @author Jeffrey You
10 | * @description Billing Subscription
11 | */
12 | @Data
13 | public class Subscription implements Serializable {
14 |
15 | @JsonProperty("object")
16 | private String object;
17 | @JsonProperty("has_payment_method")
18 | private boolean hasPaymentMethod;
19 | @JsonProperty("canceled")
20 | private boolean canceled;
21 | @JsonProperty("canceled_at")
22 | private Object canceledAt;
23 | @JsonProperty("delinquent")
24 | private Object delinquent;
25 | @JsonProperty("access_until")
26 | private long accessUntil;
27 | @JsonProperty("soft_limit")
28 | private long softLimit;
29 | @JsonProperty("hard_limit")
30 | private long hardLimit;
31 | @JsonProperty("system_hard_limit")
32 | private long systemHardLimit;
33 | @JsonProperty("soft_limit_usd")
34 | private double softLimitUsd;
35 | @JsonProperty("hard_limit_usd")
36 | private double hardLimitUsd;
37 | @JsonProperty("system_hard_limit_usd")
38 | private double systemHardLimitUsd;
39 | @JsonProperty("plan")
40 | private Plan plan;
41 | @JsonProperty("account_name")
42 | private String accountName;
43 | @JsonProperty("po_number")
44 | private Object poNumber;
45 | @JsonProperty("billing_email")
46 | private Object billingEmail;
47 | @JsonProperty("tax_ids")
48 | private Object taxIds;
49 | @JsonProperty("billing_address")
50 | private Object billingAddress;
51 | @JsonProperty("business_address")
52 | private Object businessAddress;
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/chat/ChatChoice.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.chat;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import lombok.Data;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * @author Jeffrey You
10 | * @description Chat Info
11 | */
12 | @Data
13 | public class ChatChoice implements Serializable {
14 |
15 | private long index;
16 | /** stream = true, return type is delta */
17 | @JsonProperty("delta")
18 | private Message delta;
19 | /** stream = false, return type is message */
20 | @JsonProperty("message")
21 | private Message message;
22 | @JsonProperty("finish_reason")
23 | private String finishReason;
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/chat/ChatCompletionRequest.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.chat;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import lombok.*;
6 | import lombok.extern.slf4j.Slf4j;
7 |
8 | import java.io.Serializable;
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | /**
13 | * @author Jeffrey You
14 | * @description Chat Request
15 | */
16 | @Data
17 | @Builder
18 | @Slf4j
19 | @JsonInclude(JsonInclude.Include.NON_NULL)
20 | @NoArgsConstructor
21 | @AllArgsConstructor
22 | public class ChatCompletionRequest implements Serializable {
23 |
24 | /** Default Model */
25 | private String model = Model.GPT_3_5_TURBO.getCode();
26 | /** Message */
27 | private List messages;
28 |
29 | private double temperature = 0.2;
30 |
31 | @JsonProperty("top_p")
32 | private Double topP = 1d;
33 |
34 | private Integer n = 1;
35 |
36 | private boolean stream = false;
37 |
38 | private List stop;
39 |
40 | @JsonProperty("max_tokens")
41 | private Integer maxTokens = 2048;
42 |
43 | @JsonProperty("frequency_penalty")
44 | private double frequencyPenalty = 0;
45 |
46 | @JsonProperty("presence_penalty")
47 | private double presencePenalty = 0;
48 |
49 | @JsonProperty("logit_bias")
50 | private Map logitBias;
51 |
52 | private String user;
53 |
54 | @Getter
55 | @AllArgsConstructor
56 | public enum Model {
57 | /** gpt-3.5-turbo */
58 | GPT_3_5_TURBO("gpt-3.5-turbo"),
59 | /** GPT4.0 */
60 | GPT_4("gpt-4"),
61 | /** GPT4.0 large context */
62 | GPT_4_32K("gpt-4-32k"),
63 | ;
64 | private String code;
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/chat/ChatCompletionResponse.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.chat;
2 |
3 | import com.jeffrey.chatgpt.domain.other.Usage;
4 | import lombok.Data;
5 |
6 | import java.io.Serializable;
7 | import java.util.List;
8 |
9 | /**
10 | * @author Jeffrey You
11 | * @description Chat Response
12 | */
13 | @Data
14 | public class ChatCompletionResponse implements Serializable {
15 |
16 | /** ID */
17 | private String id;
18 | /** 对象 */
19 | private String object;
20 | /** 模型 */
21 | private String model;
22 | /** 对话 */
23 | private List choices;
24 | /** 创建 */
25 | private long created;
26 | /** 耗材 */
27 | private Usage usage;
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/chat/Message.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.chat;
2 |
3 | import com.jeffrey.chatgpt.common.Constants;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 | import lombok.Data;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | * @author Jeffrey You
11 | * @description Message
12 | */
13 | @Data
14 | @JsonInclude(JsonInclude.Include.NON_NULL)
15 | public class Message implements Serializable {
16 |
17 | private String role;
18 | private String content;
19 | private String name;
20 |
21 | public Message() {
22 | }
23 |
24 | private Message(Builder builder) {
25 | this.role = builder.role;
26 | this.content = builder.content;
27 | this.name = builder.name;
28 | }
29 |
30 | public static Builder builder() {
31 | return new Builder();
32 | }
33 |
34 | /**
35 | * 建造者模式
36 | */
37 | public static final class Builder {
38 |
39 | private String role;
40 | private String content;
41 | private String name;
42 |
43 | public Builder() {
44 | }
45 |
46 | public Builder role(Constants.Role role) {
47 | this.role = role.getCode();
48 | return this;
49 | }
50 |
51 | public Builder content(String content) {
52 | this.content = content;
53 | return this;
54 | }
55 |
56 | public Builder name(String name) {
57 | this.name = name;
58 | return this;
59 | }
60 |
61 | public Message build() {
62 | return new Message(this);
63 | }
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/edits/EditRequest.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.edits;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import lombok.*;
5 | import lombok.extern.slf4j.Slf4j;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | * @author Jeffrey You
11 | * @description Edit
12 | */
13 | @Slf4j
14 | @Getter
15 | @Builder
16 | @NoArgsConstructor(force = true)
17 | @AllArgsConstructor
18 | public class EditRequest implements Serializable {
19 |
20 | @NonNull
21 | private String model = Model.CODE_DAVINCI_EDIT_001.getCode();
22 | @NonNull
23 | private String input;
24 | @NonNull
25 | private String instruction;
26 | @Builder.Default
27 | private double temperature = 0.2;
28 | @JsonProperty("top_p")
29 | private Double topP = 1d;
30 | private Integer n = 1;
31 |
32 | @Getter
33 | @AllArgsConstructor
34 | public enum Model{
35 | /** text-davinci-edit-001 */
36 | TEXT_DAVINCI_EDIT_001("text-davinci-edit-001"),
37 | /** code-davinci-edit-001 */
38 | CODE_DAVINCI_EDIT_001("code-davinci-edit-001"),
39 | ;
40 | private String code;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/edits/EditResponse.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.edits;
2 |
3 | import com.jeffrey.chatgpt.domain.other.Choice;
4 | import com.jeffrey.chatgpt.domain.other.Usage;
5 | import lombok.Data;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | * @author Jeffrey You
11 | * @description Edit
12 | */
13 | @Data
14 | public class EditResponse implements Serializable {
15 |
16 | private String id;
17 | private String object;
18 | private String model;
19 | private Choice[] choices;
20 | private long created;
21 | private Usage usage;
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/embedd/EmbeddingRequest.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.embedd;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import lombok.*;
5 | import lombok.extern.slf4j.Slf4j;
6 |
7 | import java.io.Serializable;
8 | import java.util.List;
9 |
10 | /**
11 | * @author Jeffrey You
12 | * @description Creates a variation of a given image.
13 | */
14 | @Slf4j
15 | @Getter
16 | @Builder
17 | @JsonInclude(JsonInclude.Include.NON_NULL)
18 | @NoArgsConstructor(force = true)
19 | @AllArgsConstructor
20 | public class EmbeddingRequest implements Serializable {
21 |
22 | @NonNull
23 | @Builder.Default
24 | private String model = Model.TEXT_EMBEDDING_ADA_002.getCode();
25 | @NonNull
26 | private List input;
27 | @Setter
28 | private String user;
29 |
30 | @Getter
31 | @AllArgsConstructor
32 | public enum Model {
33 | TEXT_EMBEDDING_ADA_002("text-embedding-ada-002"),
34 | ;
35 | private String code;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/embedd/EmbeddingResponse.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.embedd;
2 |
3 | import com.jeffrey.chatgpt.domain.other.Usage;
4 | import lombok.Data;
5 |
6 | import java.io.Serializable;
7 | import java.util.List;
8 |
9 | /**
10 | * @author Jeffrey You
11 | * @description Embedding Response
12 | */
13 | @Data
14 | public class EmbeddingResponse implements Serializable {
15 |
16 | private String object;
17 | private List- data;
18 | private String model;
19 | private Usage usage;
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/embedd/Item.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.embedd;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 | import java.math.BigDecimal;
7 | import java.util.List;
8 |
9 | /**
10 | * @author Jeffrey You
11 | * @description Item
12 | */
13 | @Data
14 | public class Item implements Serializable {
15 |
16 | private String object;
17 | private List embedding;
18 | private Integer index;
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/files/DeleteFileResponse.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.files;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 |
7 | /**
8 | * @author Jeffrey You
9 | * @description Delete File Response
10 | */
11 | @Data
12 | public class DeleteFileResponse implements Serializable {
13 |
14 | private String id;
15 | private String object;
16 | private boolean deleted;
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/files/File.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.files;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import lombok.Data;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * @author Jeffrey You
10 | * @description File
11 | */
12 | @Data
13 | public class File implements Serializable {
14 |
15 | private String id;
16 | private String object;
17 | private long bytes;
18 | private long created_at;
19 | private String filename;
20 | private String purpose;
21 | private String status;
22 | @JsonProperty("status_details")
23 | private String statusDetails;
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/files/UploadFileResponse.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.files;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 |
7 | /**
8 | * @author Jeffrey You
9 | * @description Upload File Response
10 | */
11 | @Data
12 | public class UploadFileResponse extends File implements Serializable {
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/images/ImageEditRequest.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.images;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import lombok.*;
6 | import lombok.extern.slf4j.Slf4j;
7 |
8 | import java.io.Serializable;
9 |
10 | /**
11 | * @author Jeffrey You
12 | * @description Upload Image
13 | */
14 | @Slf4j
15 | @Getter
16 | @Builder
17 | @JsonInclude(JsonInclude.Include.NON_NULL)
18 | @NoArgsConstructor(force = true)
19 | @AllArgsConstructor
20 | public class ImageEditRequest extends ImageEnum implements Serializable {
21 |
22 | @NonNull
23 | private String prompt;
24 | @Builder.Default
25 | private Integer n = 1;
26 | @Builder.Default
27 | private String size = Size.size_256.getCode();
28 | @JsonProperty("response_format")
29 | @Builder.Default
30 | private String responseFormat = ResponseFormat.URL.getCode();
31 | @Setter
32 | private String user;
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/images/ImageEnum.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.images;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Getter;
5 |
6 | /**
7 | * @author Jeffrey You
8 | * @description Enum Image
9 | */
10 | public class ImageEnum {
11 |
12 | @Getter
13 | @AllArgsConstructor
14 | public enum Size {
15 | size_256("256x256"),
16 | size_512("512x512"),
17 | size_1024("1024x1024"),
18 | ;
19 | private String code;
20 | }
21 |
22 | @Getter
23 | @AllArgsConstructor
24 | public enum ResponseFormat {
25 | URL("url"),
26 | B64_JSON("b64_json"),
27 | ;
28 | private String code;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/images/ImageRequest.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.images;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import lombok.*;
6 | import lombok.extern.slf4j.Slf4j;
7 |
8 | import java.io.Serializable;
9 |
10 | /**
11 | * @author Jeffrey You
12 | * @description Request Image
13 | */
14 | @Slf4j
15 | @Getter
16 | @Builder
17 | @JsonInclude(JsonInclude.Include.NON_NULL)
18 | @NoArgsConstructor(force = true)
19 | @AllArgsConstructor
20 | public class ImageRequest extends ImageEnum implements Serializable {
21 |
22 | @NonNull
23 | private String prompt;
24 | @Builder.Default
25 | private Integer n = 1;
26 | @Builder.Default
27 | private String size = Size.size_256.getCode();
28 | @JsonProperty("response_format")
29 | @Builder.Default
30 | private String responseFormat = ResponseFormat.URL.getCode();
31 | @Setter
32 | private String user;
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/images/ImageResponse.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.images;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 | import java.util.List;
7 |
8 | /**
9 | * @author Jeffrey You
10 | * @description Image Response
11 | */
12 | @Data
13 | public class ImageResponse implements Serializable {
14 | private List
- data;
15 | private long created;
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/images/Item.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.images;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import lombok.Data;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * @author Jeffrey You
10 | * @description Image
11 | */
12 | @Data
13 | public class Item implements Serializable {
14 |
15 | private String url;
16 | @JsonProperty("b64_json")
17 | private String b64Json;
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/other/Choice.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.other;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import lombok.Data;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * @author Jeffrey You
10 | * @description Choice
11 | */
12 | @Data
13 | public class Choice implements Serializable {
14 |
15 | private long index;
16 | private String text;
17 | private Object logprobs;
18 | @JsonProperty("finish_reason")
19 | private String finishReason;
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/other/OpenAiResponse.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.other;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 | import java.util.List;
7 |
8 | /**
9 | * @author Jeffrey You
10 | * @description Response
11 | */
12 | @Data
13 | public class OpenAiResponse implements Serializable {
14 |
15 | private String object;
16 | private List data;
17 | private Error error;
18 |
19 |
20 | @Data
21 | public class Error {
22 | private String message;
23 | private String type;
24 | private String param;
25 | private String code;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/other/Usage.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.other;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 |
5 | import java.io.Serializable;
6 |
7 | /**
8 | * @author Jeffrey You
9 | * @description Uasge
10 | */
11 | public class Usage implements Serializable {
12 |
13 | @JsonProperty("prompt_tokens")
14 | private long promptTokens;
15 | @JsonProperty("completion_tokens")
16 | private long completionTokens;
17 | @JsonProperty("total_tokens")
18 | private long totalTokens;
19 |
20 | public long getPromptTokens() {
21 | return promptTokens;
22 | }
23 |
24 | public void setPromptTokens(long promptTokens) {
25 | this.promptTokens = promptTokens;
26 | }
27 |
28 | public long getCompletionTokens() {
29 | return completionTokens;
30 | }
31 |
32 | public void setCompletionTokens(long completionTokens) {
33 | this.completionTokens = completionTokens;
34 | }
35 |
36 | public long getTotalTokens() {
37 | return totalTokens;
38 | }
39 |
40 | public void setTotalTokens(long totalTokens) {
41 | this.totalTokens = totalTokens;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/qa/QAChoice.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.qa;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import lombok.Data;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * @author Jeffrey You
10 | * @description Q & A Choice
11 | */
12 | @Data
13 | public class QAChoice implements Serializable {
14 |
15 | private long index;
16 | private String text;
17 | private Object logprobs;
18 | @JsonProperty("finish_reason")
19 | private String finishReason;
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/qa/QACompletionRequest.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.qa;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import lombok.*;
6 | import lombok.extern.slf4j.Slf4j;
7 |
8 | import java.io.Serializable;
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | /**
13 | * @author Jeffrey You
14 | * @description Q & A Completion Request
15 | */
16 | @Data
17 | @Builder
18 | @Slf4j
19 | @JsonInclude(JsonInclude.Include.NON_NULL)
20 | @NoArgsConstructor
21 | @AllArgsConstructor
22 | public class QACompletionRequest implements Serializable {
23 |
24 | @NonNull
25 | @Builder.Default
26 | private String model = Model.TEXT_DAVINCI_003.getCode();
27 | @NonNull
28 | private String prompt;
29 | private String suffix;
30 | private double temperature = 0.2;
31 | @JsonProperty("top_p")
32 | private Double topP = 1d;
33 | private Integer n = 1;
34 | private boolean stream = false;
35 | private List stop;
36 | @JsonProperty("max_tokens")
37 | private Integer maxTokens = 2048;
38 | @Builder.Default
39 | private boolean echo = false;
40 | @JsonProperty("frequency_penalty")
41 | private double frequencyPenalty = 0;
42 | @JsonProperty("presence_penalty")
43 | private double presencePenalty = 0;
44 | @JsonProperty("best_of")
45 | @Builder.Default
46 | private Integer bestOf = 1;
47 | private Integer logprobs;
48 | @JsonProperty("logit_bias")
49 | private Map logitBias;
50 | private String user;
51 |
52 | @Getter
53 | @AllArgsConstructor
54 | public enum Model {
55 | TEXT_DAVINCI_003("text-davinci-003"),
56 | TEXT_DAVINCI_002("text-davinci-002"),
57 | DAVINCI("davinci"),
58 | ;
59 | private String code;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/qa/QACompletionResponse.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.qa;
2 |
3 | import com.jeffrey.chatgpt.domain.other.Usage;
4 | import lombok.Data;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * @author Jeffrey You
10 | * @description Q & A Completion Response
11 | */
12 | @Data
13 | public class QACompletionResponse implements Serializable {
14 |
15 | private String id;
16 | private String object;
17 | private String model;
18 | private QAChoice[] choices;
19 | private long created;
20 | private Usage usage;
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/whisper/TranscriptionsRequest.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.whisper;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import lombok.*;
6 | import lombok.experimental.FieldNameConstants;
7 |
8 | /**
9 | * @author Jeffrey You
10 | * @description Transcriptions Request
11 | */
12 | @Data
13 | @Builder
14 | @NoArgsConstructor
15 | @AllArgsConstructor
16 | @FieldNameConstants
17 | @JsonInclude(JsonInclude.Include.NON_NULL)
18 | public class TranscriptionsRequest {
19 |
20 | @Builder.Default
21 | private String model = WhisperEnum.Model.WHISPER_1.getCode();
22 | private String prompt;
23 | @JsonProperty("response_format")
24 | @Builder.Default
25 | private String responseFormat = WhisperEnum.ResponseFormat.JSON.getCode();
26 | private double temperature = 0.2;
27 |
28 | private String language;
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/whisper/TranslationsRequest.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.whisper;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Builder;
7 | import lombok.Data;
8 | import lombok.NoArgsConstructor;
9 | import lombok.experimental.FieldNameConstants;
10 |
11 | import java.io.Serializable;
12 |
13 | /**
14 | * @author Jeffrey You
15 | * @description Translations Request
16 | */
17 | @Data
18 | @Builder
19 | @NoArgsConstructor
20 | @AllArgsConstructor
21 | @FieldNameConstants
22 | @JsonInclude(JsonInclude.Include.NON_NULL)
23 | public class TranslationsRequest implements Serializable {
24 |
25 | @Builder.Default
26 | private String model = WhisperEnum.Model.WHISPER_1.getCode();
27 | private String prompt;
28 | @JsonProperty("response_format")
29 | @Builder.Default
30 | private String responseFormat = WhisperEnum.ResponseFormat.JSON.getCode();
31 | private double temperature = 0.2;
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/whisper/WhisperEnum.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.whisper;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.Getter;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | * @author Jeffrey You
11 | * @description Audio to Text
12 | */
13 | @Data
14 | public class WhisperEnum implements Serializable {
15 |
16 | @Getter
17 | @AllArgsConstructor
18 | public enum Model {
19 | WHISPER_1("whisper-1"),
20 | ;
21 | private String code;
22 | }
23 |
24 | @Getter
25 | @AllArgsConstructor
26 | public enum ResponseFormat {
27 | JSON("json"),
28 | TEXT("text"),
29 | SRT("srt"),
30 | VERBOSE_JSON("verbose_json"),
31 | VTT("vtt"),
32 | ;
33 | private String code;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/domain/whisper/WhisperResponse.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.domain.whisper;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 |
7 | /**
8 | * @author Jeffrey You
9 | * @description Whisper Response
10 | */
11 | @Data
12 | public class WhisperResponse implements Serializable {
13 | private String text;
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/interceptor/OpenAiInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.interceptor;
2 |
3 | import cn.hutool.http.ContentType;
4 | import cn.hutool.http.Header;
5 | import okhttp3.HttpUrl;
6 | import okhttp3.Interceptor;
7 | import okhttp3.Request;
8 | import okhttp3.Response;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | import java.io.IOException;
12 |
13 | /**
14 | * @author Jeffrey You
15 | * @description Custom Interceptor
16 | */
17 | public class OpenAiInterceptor implements Interceptor {
18 |
19 | /** OpenAi apiKey */
20 | private String apiKey;
21 | /** Auth Token If needed */
22 | private String authToken;
23 |
24 | public OpenAiInterceptor(String apiKey, String authToken) {
25 | this.apiKey = apiKey;
26 | this.authToken = authToken;
27 | }
28 |
29 | @NotNull
30 | @Override
31 | public Response intercept(Chain chain) throws IOException {
32 | return chain.proceed(this.auth(apiKey, chain.request()));
33 | }
34 |
35 | private Request auth(String apiKey, Request original) {
36 | // Add token if needed
37 |
38 | // HttpUrl url = original.url().newBuilder()
39 | // .addQueryParameter("token", authToken)
40 | // .build();
41 |
42 | // Set up request.
43 | // return original.newBuilder()
44 | // .url(url)
45 | // .header(Header.AUTHORIZATION.getValue(), "Bearer " + apiKey)
46 | // .header(Header.CONTENT_TYPE.getValue(), ContentType.JSON.getValue())
47 | // .method(original.method(), original.body())
48 | // .build();
49 |
50 | // Add API Key
51 | return original.newBuilder()
52 | .header("Authorization", "Bearer " + apiKey)
53 | .build();
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/session/Configuration.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.session;
2 |
3 | import com.jeffrey.chatgpt.IOpenAiApi;
4 | import lombok.*;
5 | import lombok.extern.slf4j.Slf4j;
6 | import okhttp3.OkHttpClient;
7 | import okhttp3.sse.EventSource;
8 | import okhttp3.sse.EventSources;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | /**
12 | * @author Jeffrey You
13 | * @description Configuration
14 | */
15 | @Slf4j
16 | @Data
17 | @NoArgsConstructor
18 | @AllArgsConstructor
19 | public class Configuration {
20 |
21 | @Getter
22 | @Setter
23 | private IOpenAiApi openAiApi;
24 |
25 |
26 | @Getter
27 | @NotNull
28 | private String apiKey;
29 |
30 | @Getter
31 | private String apiHost;
32 |
33 | @Getter
34 | private String authToken;
35 |
36 | @Getter
37 | @Setter
38 | private OkHttpClient okHttpClient;
39 |
40 | public EventSource.Factory createRequestFactory() {
41 | return EventSources.createFactory(okHttpClient);
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/session/OpenAiSession.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.session;
2 |
3 | import com.jeffrey.chatgpt.domain.chat.ChatCompletionRequest;
4 | import com.jeffrey.chatgpt.domain.chat.ChatCompletionResponse;
5 | import com.jeffrey.chatgpt.domain.qa.QACompletionRequest;
6 | import com.jeffrey.chatgpt.domain.qa.QACompletionResponse;
7 | import com.fasterxml.jackson.core.JsonProcessingException;
8 | import okhttp3.sse.EventSource;
9 | import okhttp3.sse.EventSourceListener;
10 |
11 | /**
12 | * @author Jeffrey You
13 | * @description OpenAI Session
14 | */
15 | public interface OpenAiSession {
16 |
17 | /**
18 | * Q & A Model
19 | * @param qaCompletionRequest Request Body
20 | * @return Return Result
21 | */
22 | QACompletionResponse completions(QACompletionRequest qaCompletionRequest);
23 |
24 | /**
25 | * Q & A Model String Input
26 | * @param question Request Body
27 | * @return Return Result
28 | */
29 | QACompletionResponse completions(String question);
30 |
31 | /**
32 | * Q & A Model Stream
33 | * @param qaCompletionRequest Request Body
34 | * @param eventSourceListener EventSourceListener
35 | */
36 | EventSource completions(QACompletionRequest qaCompletionRequest, EventSourceListener eventSourceListener) throws JsonProcessingException;
37 |
38 |
39 | /**
40 | * Chat Model GPT-3.5/4.0
41 | * @param chatCompletionRequest Request Body
42 | * @return Return Result
43 | */
44 | ChatCompletionResponse completions(ChatCompletionRequest chatCompletionRequest);
45 |
46 | /**
47 | * Chat Model GPT-3.5/4.0 Stream
48 | * @param chatCompletionRequest Request Body
49 | * @param eventSourceListener EventSourceListener
50 | * @return Return Result
51 | */
52 | EventSource chatCompletions(ChatCompletionRequest chatCompletionRequest, EventSourceListener eventSourceListener) throws JsonProcessingException;
53 |
54 |
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/session/OpenAiSessionFactory.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.session;
2 |
3 | /**
4 | * @author Jeffrey You
5 | * @description OpenAI Session Factory
6 | */
7 | public interface OpenAiSessionFactory {
8 |
9 | OpenAiSession openSession();
10 |
11 | }
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/session/defaults/DefaultOpenAiSession.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.session.defaults;
2 |
3 | import com.jeffrey.chatgpt.domain.chat.ChatCompletionRequest;
4 | import com.jeffrey.chatgpt.domain.chat.ChatCompletionResponse;
5 | import com.jeffrey.chatgpt.domain.qa.QACompletionRequest;
6 | import com.jeffrey.chatgpt.domain.qa.QACompletionResponse;
7 | import com.jeffrey.chatgpt.session.Configuration;
8 | import com.jeffrey.chatgpt.IOpenAiApi;
9 | import com.jeffrey.chatgpt.session.OpenAiSession;
10 | import cn.hutool.http.ContentType;
11 | import com.fasterxml.jackson.core.JsonProcessingException;
12 | import com.fasterxml.jackson.databind.ObjectMapper;
13 | import io.reactivex.Single;
14 | import okhttp3.MediaType;
15 | import okhttp3.Request;
16 | import okhttp3.RequestBody;
17 | import okhttp3.sse.EventSource;
18 | import okhttp3.sse.EventSourceListener;
19 |
20 | /**
21 | * @author Jeffrey You
22 | * @description OpenAI API Session
23 | */
24 | public class DefaultOpenAiSession implements OpenAiSession {
25 |
26 | private final Configuration configuration;
27 |
28 | private final IOpenAiApi openAiApi;
29 |
30 | private final EventSource.Factory factory;
31 |
32 |
33 |
34 | public DefaultOpenAiSession(Configuration configuration) {
35 | this.configuration = configuration;
36 | this.openAiApi = configuration.getOpenAiApi();
37 | this.factory = configuration.createRequestFactory();
38 | }
39 |
40 | @Override
41 | public QACompletionResponse completions(QACompletionRequest qaCompletionRequest) {
42 | return this.openAiApi.completions(qaCompletionRequest).blockingGet();
43 | }
44 |
45 | @Override
46 | public QACompletionResponse completions(String question) {
47 | QACompletionRequest request = QACompletionRequest
48 | .builder()
49 | .prompt(question)
50 | .build();
51 | Single completions = this.openAiApi.completions(request);
52 | return completions.blockingGet();
53 | }
54 |
55 | @Override
56 | public EventSource completions(QACompletionRequest qaCompletionRequest, EventSourceListener eventSourceListener) throws JsonProcessingException {
57 | if (!qaCompletionRequest.isStream()){
58 | throw new RuntimeException("illegal parameter stream is false!");
59 | }
60 |
61 | Request request = new Request.Builder()
62 | .url(configuration.getApiHost().concat(IOpenAiApi.v1_completions))
63 | .post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), new ObjectMapper().writeValueAsString(qaCompletionRequest)))
64 | .build();
65 |
66 | return factory.newEventSource(request, eventSourceListener);
67 |
68 | }
69 |
70 | @Override
71 | public ChatCompletionResponse completions(ChatCompletionRequest chatCompletionRequest) {
72 | return this.openAiApi.completions(chatCompletionRequest).blockingGet();
73 | }
74 |
75 | @Override
76 | public EventSource chatCompletions(ChatCompletionRequest chatCompletionRequest, EventSourceListener eventSourceListener) throws JsonProcessingException {
77 | if (!chatCompletionRequest.isStream()){
78 | throw new RuntimeException("illegal parameter stream is false!");
79 | }
80 |
81 | Request request = new Request.Builder()
82 | .url(configuration.getApiHost().concat(IOpenAiApi.v1_chat_completions))
83 | .post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), new ObjectMapper().writeValueAsString(chatCompletionRequest)))
84 | .build();
85 |
86 | return factory.newEventSource(request, eventSourceListener);
87 | }
88 |
89 | }
--------------------------------------------------------------------------------
/src/main/java/com/jeffrey/chatgpt/session/defaults/DefaultOpenAiSessionFactory.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.session.defaults;
2 |
3 | import com.jeffrey.chatgpt.IOpenAiApi;
4 | import com.jeffrey.chatgpt.interceptor.OpenAiInterceptor;
5 | import com.jeffrey.chatgpt.session.Configuration;
6 | import com.jeffrey.chatgpt.session.OpenAiSession;
7 | import com.jeffrey.chatgpt.session.OpenAiSessionFactory;
8 | import okhttp3.OkHttpClient;
9 | import okhttp3.logging.HttpLoggingInterceptor;
10 | import retrofit2.Retrofit;
11 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
12 | import retrofit2.converter.jackson.JacksonConverterFactory;
13 |
14 | import java.util.concurrent.TimeUnit;
15 |
16 | /**
17 | * @author Jeffrey You
18 | * @description OpenAI API Factory
19 | */
20 | public class DefaultOpenAiSessionFactory implements OpenAiSessionFactory {
21 |
22 | private final Configuration configuration;
23 |
24 | public DefaultOpenAiSessionFactory(Configuration configuration) {
25 | this.configuration = configuration;
26 | }
27 |
28 | @Override
29 | public OpenAiSession openSession() {
30 | // 1. 日志配置
31 | HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
32 | httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
33 |
34 | // 2. 开启 Http 客户端
35 | OkHttpClient okHttpClient = new OkHttpClient
36 | .Builder()
37 | .addInterceptor(httpLoggingInterceptor)
38 | .addInterceptor(new OpenAiInterceptor(configuration.getApiKey(), configuration.getAuthToken()))
39 | .connectTimeout(450, TimeUnit.SECONDS)
40 | .writeTimeout(450, TimeUnit.SECONDS)
41 | .readTimeout(450, TimeUnit.SECONDS)
42 | .build();
43 | configuration.setOkHttpClient(okHttpClient);
44 |
45 |
46 | // 3. 创建 API 服务
47 | IOpenAiApi openAiApi = new Retrofit.Builder()
48 | .baseUrl(configuration.getApiHost())
49 | .client(okHttpClient)
50 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
51 | .addConverterFactory(JacksonConverterFactory.create())
52 | .build().create(IOpenAiApi.class);
53 |
54 | configuration.setOpenAiApi(openAiApi);
55 |
56 | return new DefaultOpenAiSession(configuration);
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/test/java/com/jeffrey/chatgpt/test/ApiTest.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.test;
2 |
3 | import com.jeffrey.chatgpt.common.Constants;
4 | import com.jeffrey.chatgpt.domain.chat.ChatCompletionRequest;
5 | import com.jeffrey.chatgpt.domain.chat.ChatCompletionResponse;
6 | import com.jeffrey.chatgpt.domain.chat.Message;
7 | import com.jeffrey.chatgpt.domain.qa.QACompletionRequest;
8 | import com.jeffrey.chatgpt.domain.qa.QACompletionResponse;
9 | import com.jeffrey.chatgpt.session.Configuration;
10 | import com.jeffrey.chatgpt.session.OpenAiSession;
11 | import com.jeffrey.chatgpt.session.OpenAiSessionFactory;
12 | import com.jeffrey.chatgpt.session.defaults.DefaultOpenAiSessionFactory;
13 | import com.fasterxml.jackson.core.JsonProcessingException;
14 | import com.fasterxml.jackson.databind.ObjectMapper;
15 | import lombok.extern.slf4j.Slf4j;
16 | import okhttp3.sse.EventSource;
17 | import okhttp3.sse.EventSourceListener;
18 | import org.junit.Before;
19 | import org.junit.Test;
20 |
21 | import java.util.Collections;
22 | import java.util.concurrent.CountDownLatch;
23 |
24 | /**
25 | * @author Jeffrey You
26 | * @description API Test
27 | */
28 | @Slf4j
29 | public class ApiTest {
30 |
31 | private OpenAiSession openAiSession;
32 |
33 | @Before
34 | public void test_OpenAiSessionFactory() {
35 | // 1. Configuration
36 | Configuration configuration = new Configuration();
37 | configuration.setApiHost("https://api.openai.com/");
38 | configuration.setApiKey("Please input your API Key");
39 | // 2. SessionFactory
40 | OpenAiSessionFactory factory = new DefaultOpenAiSessionFactory(configuration);
41 | // 3. Open Session
42 | this.openAiSession = factory.openSession();
43 | }
44 |
45 | /**
46 | * Q & A Model
47 | */
48 | @Test
49 | public void test_qa_completions() throws JsonProcessingException {
50 | QACompletionResponse response01 = openAiSession.completions("Write Bubble Sort in Java");
51 | log.info("Test Result:{}", new ObjectMapper().writeValueAsString(response01.getChoices()));
52 | }
53 |
54 | /**
55 | * Q & A Model Stream
56 | */
57 | @Test
58 | public void test_qa_completions_stream() throws JsonProcessingException, InterruptedException {
59 | // 1. Create Request
60 | QACompletionRequest request = QACompletionRequest
61 | .builder()
62 | .prompt("Write Bubble Sort in Java")
63 | .stream(true)
64 | .build();
65 |
66 | for (int i = 0; i < 1; i++) {
67 | // 2. Send Request
68 | EventSource eventSource = openAiSession.completions(request, new EventSourceListener() {
69 | @Override
70 | public void onEvent(EventSource eventSource, String id, String type, String data) {
71 | log.info("Test Result:{}", data);
72 | }
73 | });
74 | }
75 | // Wait Finish
76 | new CountDownLatch(1).await();
77 | }
78 |
79 |
80 | /**
81 | * Chat Model
82 | */
83 | @Test
84 | public void test_chat_completions() {
85 | // 1. Create Request
86 | ChatCompletionRequest chatCompletion = ChatCompletionRequest
87 | .builder()
88 | .messages(Collections.singletonList(Message.builder().role(Constants.Role.USER).content("Write Bubble Sort in Java").build()))
89 | .model(ChatCompletionRequest.Model.GPT_3_5_TURBO.getCode())
90 | .build();
91 | // 2. Send Request
92 | ChatCompletionResponse chatCompletionResponse = openAiSession.completions(chatCompletion);
93 | // 3. Print Result
94 | chatCompletionResponse.getChoices().forEach(e -> {
95 | log.info("Test Result:{}", e.getMessage());
96 | });
97 | }
98 |
99 | /**
100 | * Chat Model Stream
101 | */
102 | @Test
103 | public void test_chat_completions_stream() throws JsonProcessingException, InterruptedException {
104 | // 1. Create Request
105 | ChatCompletionRequest chatCompletion = ChatCompletionRequest
106 | .builder()
107 | .stream(true)
108 | .messages(Collections.singletonList(Message.builder().role(Constants.Role.USER).content("Write Bubble Sort in Java").build()))
109 | .model(ChatCompletionRequest.Model.GPT_3_5_TURBO.getCode())
110 | .build();
111 | // 2. Send Request
112 | EventSource eventSource = openAiSession.chatCompletions(chatCompletion, new EventSourceListener() {
113 | @Override
114 | public void onEvent(EventSource eventSource, String id, String type, String data) {
115 | log.info("Test Result:{}", data);
116 | }
117 | });
118 | // 3. Wait Finish
119 | new CountDownLatch(1).await();
120 | }
121 |
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/src/test/java/com/jeffrey/chatgpt/test/ClientTest.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.test;
2 |
3 | import com.jeffrey.chatgpt.common.Constants;
4 | import com.jeffrey.chatgpt.domain.chat.ChatCompletionRequest;
5 | import com.jeffrey.chatgpt.domain.chat.ChatCompletionResponse;
6 | import com.jeffrey.chatgpt.domain.chat.Message;
7 | import com.jeffrey.chatgpt.session.Configuration;
8 | import com.jeffrey.chatgpt.session.OpenAiSession;
9 | import com.jeffrey.chatgpt.session.OpenAiSessionFactory;
10 | import com.jeffrey.chatgpt.session.defaults.DefaultOpenAiSessionFactory;
11 |
12 | import java.util.ArrayList;
13 | import java.util.Scanner;
14 |
15 | /**
16 | * @author Jeffrey You
17 | * @description Client Test
18 | */
19 | public class ClientTest {
20 |
21 | public static void main(String[] args) throws InterruptedException {
22 | Configuration configuration = new Configuration();
23 | configuration.setApiHost("https://api.openai.com/");
24 | configuration.setApiKey("Please enter your API key here");
25 | OpenAiSessionFactory factory = new DefaultOpenAiSessionFactory(configuration);
26 | OpenAiSession openAiSession = factory.openSession();
27 |
28 | System.out.println("Please enter the question:");
29 |
30 | ChatCompletionRequest chatCompletion = ChatCompletionRequest
31 | .builder()
32 | .messages(new ArrayList<>())
33 | .model(ChatCompletionRequest.Model.GPT_3_5_TURBO.getCode())
34 | .user("testUser01")
35 | .build();
36 |
37 | Scanner scanner = new Scanner(System.in);
38 | while (scanner.hasNextLine()) {
39 | String text = scanner.nextLine();
40 | chatCompletion.getMessages().add(Message.builder().role(Constants.Role.USER).content(text).build());
41 | ChatCompletionResponse chatCompletionResponse = openAiSession.completions(chatCompletion);
42 | chatCompletion.getMessages().add(Message.builder().role(Constants.Role.USER).content(chatCompletionResponse.getChoices().get(0).getMessage().getContent()).build());
43 |
44 | System.out.println(chatCompletionResponse.getChoices().get(0).getMessage().getContent());
45 | System.out.println("Please enter your question:");
46 | }
47 |
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/test/java/com/jeffrey/chatgpt/test/HttpClientTest.java:
--------------------------------------------------------------------------------
1 | package com.jeffrey.chatgpt.test;
2 |
3 | import com.jeffrey.chatgpt.IOpenAiApi;
4 | import com.jeffrey.chatgpt.common.Constants;
5 | import com.jeffrey.chatgpt.domain.chat.ChatCompletionRequest;
6 | import com.jeffrey.chatgpt.domain.chat.ChatCompletionResponse;
7 | import com.jeffrey.chatgpt.domain.chat.Message;
8 | import cn.hutool.http.ContentType;
9 | import cn.hutool.http.Header;
10 | import com.fasterxml.jackson.core.JsonProcessingException;
11 | import com.fasterxml.jackson.databind.ObjectMapper;
12 | import io.reactivex.Single;
13 | import lombok.extern.slf4j.Slf4j;
14 | import okhttp3.*;
15 | import okhttp3.logging.HttpLoggingInterceptor;
16 | import okhttp3.sse.EventSource;
17 | import okhttp3.sse.EventSourceListener;
18 | import okhttp3.sse.EventSources;
19 | import org.junit.Test;
20 | import retrofit2.Retrofit;
21 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
22 | import retrofit2.converter.jackson.JacksonConverterFactory;
23 |
24 | import java.util.Collections;
25 | import java.util.concurrent.CountDownLatch;
26 |
27 | /**
28 | * @author Jeffrey You
29 | * @description Http Client Test
30 | */
31 | @Slf4j
32 | public class HttpClientTest {
33 |
34 | private String openAiKey = "Please enter your API key here";
35 |
36 | @Test
37 | public void test_normal() {
38 | HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
39 | httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
40 |
41 | OkHttpClient okHttpClient = new OkHttpClient
42 | .Builder()
43 | .addInterceptor(httpLoggingInterceptor)
44 | .addInterceptor(chain -> {
45 | Request original = chain.request();
46 |
47 | HttpUrl url = original.url();
48 | Request request = original.newBuilder()
49 | .url(url)
50 | .header(Header.AUTHORIZATION.getValue(), "Bearer " + this.openAiKey)
51 | .header(Header.CONTENT_TYPE.getValue(), ContentType.JSON.getValue())
52 | .method(original.method(), original.body())
53 | .build();
54 | return chain.proceed(request);
55 | })
56 | .build();
57 |
58 | IOpenAiApi openAiApi = new Retrofit.Builder()
59 | .baseUrl("https://api.openai.com/")
60 | .client(okHttpClient)
61 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
62 | .addConverterFactory(JacksonConverterFactory.create())
63 | .build().create(IOpenAiApi.class);
64 |
65 | Message message = Message.builder().role(Constants.Role.USER).content("Hello").build();
66 | ChatCompletionRequest chatCompletion = ChatCompletionRequest
67 | .builder()
68 | .messages(Collections.singletonList(message))
69 | .model(ChatCompletionRequest.Model.GPT_3_5_TURBO.getCode())
70 | .build();
71 |
72 | Single chatCompletionResponseSingle = openAiApi.completions(chatCompletion);
73 | ChatCompletionResponse chatCompletionResponse = chatCompletionResponseSingle.blockingGet();
74 | chatCompletionResponse.getChoices().forEach(e -> {
75 | System.out.println(e.getMessage());
76 | });
77 | }
78 |
79 | @Test
80 | public void test_client_stream() throws JsonProcessingException, InterruptedException {
81 | HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
82 | httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
83 |
84 | OkHttpClient okHttpClient = new OkHttpClient
85 | .Builder()
86 | .addInterceptor(httpLoggingInterceptor)
87 | .addInterceptor(chain -> {
88 | Request original = chain.request();
89 |
90 |
91 | HttpUrl url = original.url();
92 | Request request = original.newBuilder()
93 | .url(url)
94 | .header(Header.AUTHORIZATION.getValue(), "Bearer " + this.openAiKey)
95 | .header(Header.CONTENT_TYPE.getValue(), ContentType.JSON.getValue())
96 | .method(original.method(), original.body())
97 | .build();
98 | return chain.proceed(request);
99 | })
100 | .build();
101 |
102 | Message message = Message.builder().role(Constants.Role.USER).content("Hello").build();
103 | ChatCompletionRequest chatCompletion = ChatCompletionRequest
104 | .builder()
105 | .messages(Collections.singletonList(message))
106 | .model(ChatCompletionRequest.Model.GPT_3_5_TURBO.getCode())
107 | .stream(true)
108 | .build();
109 |
110 | EventSource.Factory factory = EventSources.createFactory(okHttpClient);
111 | String requestBody = new ObjectMapper().writeValueAsString(chatCompletion);
112 |
113 | Request request = new Request.Builder()
114 | .url("https://api.openai.com/v1/chat/completions")
115 | .post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), requestBody))
116 | .build();
117 |
118 | EventSource eventSource = factory.newEventSource(request, new EventSourceListener() {
119 | @Override
120 | public void onEvent(EventSource eventSource, String id, String type, String data) {
121 | log.info("Test Result:{}", data);
122 | }
123 | });
124 |
125 | new CountDownLatch(1).await();
126 |
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------