functions;
+
+ /**
+ * 取值:null,auto或者自定义
+ * functions没有值的时候默认为:null
+ * functions存在值得时候默认为:auto
+ * 也可以自定义
+ */
+ @JsonProperty("function_call")
+ private Object functionCall;
+
/**
* 使用什么取样温度,0到2之间。较高的值(如0.8)将使输出更加随机,而较低的值(如0.2)将使输出更加集中和确定。
*
@@ -108,7 +120,10 @@ public long tokens() {
return TikTokensUtil.tokens(this.model, this.messages);
}
-
+ /**
+ * 最新模型参考官方文档:
+ * 官方稳定模型列表
+ */
@Getter
@AllArgsConstructor
public enum Model {
@@ -117,25 +132,48 @@ public enum Model {
*/
GPT_3_5_TURBO("gpt-3.5-turbo"),
/**
- * 临时模型,不建议使用
+ * 临时模型,不建议使用,2023年9 月 13 日将被弃用
*/
+ @Deprecated
GPT_3_5_TURBO_0301("gpt-3.5-turbo-0301"),
+ /**
+ * gpt-3.5-turbo-0613 支持函数
+ */
+ GPT_3_5_TURBO_0613("gpt-3.5-turbo-0613"),
+ /**
+ * gpt-3.5-turbo-16k 超长上下文
+ */
+ GPT_3_5_TURBO_16K("gpt-3.5-turbo-16k"),
+ /**
+ * gpt-3.5-turbo-16k-0613 超长上下文 支持函数
+ */
+ GPT_3_5_TURBO_16K_0613("gpt-3.5-turbo-16k-0613"),
/**
* GPT4.0
*/
GPT_4("gpt-4"),
/**
- * 临时模型,不建议使用
+ * 临时模型,不建议使用,2023年9 月 13 日将被弃用
*/
+ @Deprecated
GPT_4_0314("gpt-4-0314"),
/**
* GPT4.0 超长上下文
*/
GPT_4_32K("gpt-4-32k"),
/**
- * 临时模型,不建议使用
+ * 临时模型,不建议使用,2023年9 月 13 日将被弃用
*/
GPT_4_32K_0314("gpt-4-32k-0314"),
+
+ /**
+ * gpt-4-0613,支持函数
+ */
+ GPT_4_0613("gpt-4-0613"),
+ /**
+ * gpt-4-0613,支持函数
+ */
+ GPT_4_32K_0613("gpt-4-32k-0613"),
;
private String name;
}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/chat/ChatCompletionResponse.java b/src/main/java/com/unfbx/chatgpt/entity/chat/ChatCompletionResponse.java
index 7d59516..4c834ab 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/chat/ChatCompletionResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/chat/ChatCompletionResponse.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.chat;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.unfbx.chatgpt.entity.common.Usage;
import lombok.Data;
@@ -13,6 +14,7 @@
* 2023-03-02
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class ChatCompletionResponse implements Serializable {
private String id;
private String object;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/chat/FunctionCall.java b/src/main/java/com/unfbx/chatgpt/entity/chat/FunctionCall.java
new file mode 100644
index 0000000..6464461
--- /dev/null
+++ b/src/main/java/com/unfbx/chatgpt/entity/chat/FunctionCall.java
@@ -0,0 +1,28 @@
+package com.unfbx.chatgpt.entity.chat;
+
+import cn.hutool.json.JSONUtil;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 描述:函数调用返回值
+ *
+ * @author https://www.unfbx.com
+ * @since 2023-06-14
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class FunctionCall {
+ /**
+ * 方法名
+ */
+ private String name;
+ /**
+ * 方法参数
+ */
+ private String arguments;
+}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/chat/Functions.java b/src/main/java/com/unfbx/chatgpt/entity/chat/Functions.java
new file mode 100644
index 0000000..c0ec391
--- /dev/null
+++ b/src/main/java/com/unfbx/chatgpt/entity/chat/Functions.java
@@ -0,0 +1,47 @@
+package com.unfbx.chatgpt.entity.chat;
+
+import cn.hutool.core.date.StopWatch;
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 描述:方法参数实体类,实例数据如下
+ *
+ * {
+ * "name": "get_current_weather",
+ * "description": "Get the current weather in a given location",
+ * "parameters": {
+ * "type": "object",
+ * "properties": {
+ * "location": {
+ * "type": "string",
+ * "description": "The city and state, e.g. San Francisco, CA"
+ * },
+ * "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
+ * },
+ * "required": ["location"]
+ * },
+ * }
+ *
+ * @author https:www.unfbx.com
+ * @since 2023-06-14
+ */
+@Data
+@Builder
+public class Functions implements Serializable {
+ /**
+ * 方法名称
+ */
+ private String name;
+ /**
+ * 方法描述
+ */
+ private String description;
+ /**
+ * 方法参数
+ * 扩展参数可以继承Parameters自己实现,json格式的数据
+ */
+ private Parameters parameters;
+}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/chat/Message.java b/src/main/java/com/unfbx/chatgpt/entity/chat/Message.java
index 56ad5b7..5ee5402 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/chat/Message.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/chat/Message.java
@@ -1,6 +1,8 @@
package com.unfbx.chatgpt.entity.chat;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
@@ -16,10 +18,12 @@
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Message implements Serializable {
/**
- * 目前支持三中角色参考官网,进行情景输入:https://platform.openai.com/docs/guides/chat/introduction
+ * 目前支持四个中角色参考官网,进行情景输入:
+ * https://platform.openai.com/docs/guides/chat/introduction
*/
private String role;
@@ -27,6 +31,9 @@ public class Message implements Serializable {
private String name;
+ @JsonProperty("function_call")
+ private FunctionCall functionCall;
+
public static Builder builder() {
return new Builder();
}
@@ -34,14 +41,16 @@ public static Builder builder() {
/**
* 构造函数
*
- * @param role 角色
- * @param content 描述主题信息
- * @param name name
+ * @param role 角色
+ * @param content 描述主题信息
+ * @param name name
+ * @param functionCall functionCall
*/
- public Message(String role, String content, String name) {
+ public Message(String role, String content, String name, FunctionCall functionCall) {
this.role = role;
this.content = content;
this.name = name;
+ this.functionCall = functionCall;
}
public Message() {
@@ -51,6 +60,7 @@ private Message(Builder builder) {
setRole(builder.role);
setContent(builder.content);
setName(builder.name);
+ setFunctionCall(builder.functionCall);
}
@@ -61,6 +71,7 @@ public enum Role {
SYSTEM("system"),
USER("user"),
ASSISTANT("assistant"),
+ FUNCTION("function"),
;
private String name;
}
@@ -69,6 +80,7 @@ public static final class Builder {
private String role;
private String content;
private String name;
+ private FunctionCall functionCall;
public Builder() {
}
@@ -78,6 +90,11 @@ public Builder role(Role role) {
return this;
}
+ public Builder role(String role) {
+ this.role = role;
+ return this;
+ }
+
public Builder content(String content) {
this.content = content;
return this;
@@ -88,6 +105,11 @@ public Builder name(String name) {
return this;
}
+ public Builder functionCall(FunctionCall functionCall) {
+ this.functionCall = functionCall;
+ return this;
+ }
+
public Message build() {
return new Message(this);
}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/chat/Parameters.java b/src/main/java/com/unfbx/chatgpt/entity/chat/Parameters.java
new file mode 100644
index 0000000..08ae69d
--- /dev/null
+++ b/src/main/java/com/unfbx/chatgpt/entity/chat/Parameters.java
@@ -0,0 +1,42 @@
+package com.unfbx.chatgpt.entity.chat;
+
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+/**
+ * 描述:方法参数类,扩展参数可以继承Parameters自己实现
+ * 参考:
+ *
+ * {
+ * "type": "object",
+ * "properties": {
+ * "location": {
+ * "type": "string",
+ * "description": "The city and state, e.g. San Francisco, CA"
+ * },
+ * "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
+ * },
+ * "required": ["location"]
+ * }
+ *
+ * @author https:www.unfbx.com
+ * @since 2023-06-14
+ */
+@Data
+@Builder
+public class Parameters implements Serializable {
+ /**
+ * 参数类型
+ */
+ private String type;
+ /**
+ * 参数属性、描述
+ */
+ private Object properties;
+ /**
+ * 方法必输字段
+ */
+ private List required;
+}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/common/Choice.java b/src/main/java/com/unfbx/chatgpt/entity/common/Choice.java
index 98b7fb4..3a319d3 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/common/Choice.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/common/Choice.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.common;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@@ -12,6 +13,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Choice implements Serializable {
private String text;
private long index;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/common/DeleteResponse.java b/src/main/java/com/unfbx/chatgpt/entity/common/DeleteResponse.java
index 4def371..5cb560d 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/common/DeleteResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/common/DeleteResponse.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.common;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
@@ -11,6 +12,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class DeleteResponse implements Serializable {
private String id;
private String object;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/common/OpenAiResponse.java b/src/main/java/com/unfbx/chatgpt/entity/common/OpenAiResponse.java
index 6ab56fc..ed4bf87 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/common/OpenAiResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/common/OpenAiResponse.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.common;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
@@ -11,6 +12,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class OpenAiResponse implements Serializable {
private String object;
private List data;
@@ -18,6 +20,7 @@ public class OpenAiResponse implements Serializable {
@Data
+ @JsonIgnoreProperties(ignoreUnknown = true)
public class Error {
private String message;
private String type;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/common/Usage.java b/src/main/java/com/unfbx/chatgpt/entity/common/Usage.java
index 4c34afd..31b4368 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/common/Usage.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/common/Usage.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.common;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@@ -12,6 +13,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Usage implements Serializable {
@JsonProperty("prompt_tokens")
private long promptTokens;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/completions/Completion.java b/src/main/java/com/unfbx/chatgpt/entity/completions/Completion.java
index 77fb645..da8b646 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/completions/Completion.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/completions/Completion.java
@@ -104,7 +104,7 @@ public class Completion implements Serializable {
/**
* 获取当前参数的tokens数
- * @return
+ * @return token数量
*/
public long tokens() {
if (StrUtil.isBlank(this.prompt) || StrUtil.isBlank(this.model)) {
diff --git a/src/main/java/com/unfbx/chatgpt/entity/completions/CompletionResponse.java b/src/main/java/com/unfbx/chatgpt/entity/completions/CompletionResponse.java
index 0b47656..9fea9d2 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/completions/CompletionResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/completions/CompletionResponse.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.completions;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.unfbx.chatgpt.entity.common.OpenAiResponse;
import com.unfbx.chatgpt.entity.common.Choice;
import com.unfbx.chatgpt.entity.common.Usage;
@@ -14,6 +15,7 @@
* 2023-02-11
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class CompletionResponse extends OpenAiResponse implements Serializable {
private String id;
private String object;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/edits/EditResponse.java b/src/main/java/com/unfbx/chatgpt/entity/edits/EditResponse.java
index b47f52f..e5a1e26 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/edits/EditResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/edits/EditResponse.java
@@ -1,6 +1,7 @@
package com.unfbx.chatgpt.entity.edits;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.unfbx.chatgpt.entity.common.Choice;
import com.unfbx.chatgpt.entity.common.Usage;
import lombok.Data;
@@ -14,6 +15,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class EditResponse implements Serializable {
private String id;
private String object;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/embeddings/EmbeddingResponse.java b/src/main/java/com/unfbx/chatgpt/entity/embeddings/EmbeddingResponse.java
index 60e41ab..c5da58a 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/embeddings/EmbeddingResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/embeddings/EmbeddingResponse.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.embeddings;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.unfbx.chatgpt.entity.common.Usage;
import lombok.Data;
@@ -14,6 +15,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class EmbeddingResponse implements Serializable {
private String object;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/embeddings/Item.java b/src/main/java/com/unfbx/chatgpt/entity/embeddings/Item.java
index a7de196..c7e09c7 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/embeddings/Item.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/embeddings/Item.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.embeddings;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
@@ -7,6 +8,7 @@
import java.util.List;
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Item implements Serializable {
private String object;
private List embedding;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/engines/Engine.java b/src/main/java/com/unfbx/chatgpt/entity/engines/Engine.java
index caad045..e286714 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/engines/Engine.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/engines/Engine.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.engines;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
@@ -11,6 +12,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Engine implements Serializable {
private String id;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/files/File.java b/src/main/java/com/unfbx/chatgpt/entity/files/File.java
index 5c943ea..2577bbc 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/files/File.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/files/File.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.files;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@@ -12,6 +13,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class File implements Serializable {
private String id;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/files/UploadFileResponse.java b/src/main/java/com/unfbx/chatgpt/entity/files/UploadFileResponse.java
index 2420651..8e65ccc 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/files/UploadFileResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/files/UploadFileResponse.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.files;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
@@ -11,5 +12,6 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class UploadFileResponse extends File implements Serializable {
}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/fineTune/Event.java b/src/main/java/com/unfbx/chatgpt/entity/fineTune/Event.java
index 7852213..34503fe 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/fineTune/Event.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/fineTune/Event.java
@@ -1,11 +1,13 @@
package com.unfbx.chatgpt.entity.fineTune;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Event implements Serializable {
private String object;
@JsonProperty("created_at")
diff --git a/src/main/java/com/unfbx/chatgpt/entity/fineTune/FineTuneDeleteResponse.java b/src/main/java/com/unfbx/chatgpt/entity/fineTune/FineTuneDeleteResponse.java
index 8310ea4..192c9ce 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/fineTune/FineTuneDeleteResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/fineTune/FineTuneDeleteResponse.java
@@ -1,10 +1,12 @@
package com.unfbx.chatgpt.entity.fineTune;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class FineTuneDeleteResponse implements Serializable {
private String id;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/fineTune/FineTuneResponse.java b/src/main/java/com/unfbx/chatgpt/entity/fineTune/FineTuneResponse.java
index 751cc92..f8f3357 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/fineTune/FineTuneResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/fineTune/FineTuneResponse.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.fineTune;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@@ -7,6 +8,7 @@
import java.util.List;
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class FineTuneResponse implements Serializable {
private String id;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/fineTune/HyperParam.java b/src/main/java/com/unfbx/chatgpt/entity/fineTune/HyperParam.java
index 422f585..8a9d799 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/fineTune/HyperParam.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/fineTune/HyperParam.java
@@ -1,11 +1,13 @@
package com.unfbx.chatgpt.entity.fineTune;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class HyperParam implements Serializable {
@JsonProperty("batch_size")
diff --git a/src/main/java/com/unfbx/chatgpt/entity/fineTune/TrainingFile.java b/src/main/java/com/unfbx/chatgpt/entity/fineTune/TrainingFile.java
index a61b314..44cc6bb 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/fineTune/TrainingFile.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/fineTune/TrainingFile.java
@@ -1,11 +1,13 @@
package com.unfbx.chatgpt.entity.fineTune;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class TrainingFile implements Serializable {
private String id;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/images/ImageResponse.java b/src/main/java/com/unfbx/chatgpt/entity/images/ImageResponse.java
index c607cc4..e795f02 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/images/ImageResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/images/ImageResponse.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.images;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
@@ -12,6 +13,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class ImageResponse implements Serializable {
private long created;
private List- data;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/images/Item.java b/src/main/java/com/unfbx/chatgpt/entity/images/Item.java
index 27cc6ce..89a3142 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/images/Item.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/images/Item.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.images;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@@ -12,6 +13,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Item implements Serializable {
private String url;
@JsonProperty("b64_json")
diff --git a/src/main/java/com/unfbx/chatgpt/entity/models/Model.java b/src/main/java/com/unfbx/chatgpt/entity/models/Model.java
index 18c3279..18fcf39 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/models/Model.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/models/Model.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.models;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@@ -13,6 +14,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Model implements Serializable {
private String id;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/models/ModelResponse.java b/src/main/java/com/unfbx/chatgpt/entity/models/ModelResponse.java
index ddc87ed..84d226e 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/models/ModelResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/models/ModelResponse.java
@@ -1,6 +1,6 @@
package com.unfbx.chatgpt.entity.models;
-import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
@@ -13,6 +13,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class ModelResponse implements Serializable {
private String object;
private List data;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/models/Permission.java b/src/main/java/com/unfbx/chatgpt/entity/models/Permission.java
index 4f1be12..c52cdc8 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/models/Permission.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/models/Permission.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.models;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@@ -12,6 +13,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Permission implements Serializable {
private String id;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/moderations/Categories.java b/src/main/java/com/unfbx/chatgpt/entity/moderations/Categories.java
index 951c861..33627c8 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/moderations/Categories.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/moderations/Categories.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.moderations;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@@ -12,6 +13,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Categories implements Serializable {
/**
* 表达、煽动或宣扬基于种族、性别、民族、宗教、国籍、性取向、残疾状况或种姓的仇恨的内容。
diff --git a/src/main/java/com/unfbx/chatgpt/entity/moderations/CategoryScores.java b/src/main/java/com/unfbx/chatgpt/entity/moderations/CategoryScores.java
index 11ed85e..b244ea8 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/moderations/CategoryScores.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/moderations/CategoryScores.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.moderations;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@@ -13,6 +14,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class CategoryScores implements Serializable {
private BigDecimal hate;
@JsonProperty("hate/threatening")
diff --git a/src/main/java/com/unfbx/chatgpt/entity/moderations/ModerationResponse.java b/src/main/java/com/unfbx/chatgpt/entity/moderations/ModerationResponse.java
index e11cd55..d9ab389 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/moderations/ModerationResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/moderations/ModerationResponse.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.moderations;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
@@ -12,6 +13,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class ModerationResponse implements Serializable {
private String id;
private String model;
diff --git a/src/main/java/com/unfbx/chatgpt/entity/moderations/Result.java b/src/main/java/com/unfbx/chatgpt/entity/moderations/Result.java
index fd3c079..2f2bd4f 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/moderations/Result.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/moderations/Result.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.moderations;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@@ -12,6 +13,7 @@
* 2023-02-15
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Result implements Serializable {
private Categories categories;
@JsonProperty("category_scores")
diff --git a/src/main/java/com/unfbx/chatgpt/entity/whisper/WhisperResponse.java b/src/main/java/com/unfbx/chatgpt/entity/whisper/WhisperResponse.java
index 5de5654..c4b4028 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/whisper/WhisperResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/whisper/WhisperResponse.java
@@ -1,5 +1,6 @@
package com.unfbx.chatgpt.entity.whisper;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
@@ -11,6 +12,7 @@
* @since 2023-03-02
*/
@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
public class WhisperResponse implements Serializable {
private String text;
diff --git a/src/main/java/com/unfbx/chatgpt/function/KeyRandomStrategy.java b/src/main/java/com/unfbx/chatgpt/function/KeyRandomStrategy.java
index fa3dc1e..ede96d8 100644
--- a/src/main/java/com/unfbx/chatgpt/function/KeyRandomStrategy.java
+++ b/src/main/java/com/unfbx/chatgpt/function/KeyRandomStrategy.java
@@ -5,7 +5,7 @@
import java.util.List;
/**
- * 描述:
+ * 描述:随机策略
*
* @author https:www.unfbx.com
* @since 2023-04-03
diff --git a/src/main/java/com/unfbx/chatgpt/interceptor/DefaultOpenAiAuthInterceptor.java b/src/main/java/com/unfbx/chatgpt/interceptor/DefaultOpenAiAuthInterceptor.java
index 394d8da..b6ac618 100644
--- a/src/main/java/com/unfbx/chatgpt/interceptor/DefaultOpenAiAuthInterceptor.java
+++ b/src/main/java/com/unfbx/chatgpt/interceptor/DefaultOpenAiAuthInterceptor.java
@@ -37,7 +37,7 @@ public DefaultOpenAiAuthInterceptor(Map warringConfig) {
*
* @param chain Chain
* @return Response对象
- * @throws IOException
+ * @throws IOException io异常
*/
@Override
public Response intercept(Chain chain) throws IOException {
diff --git a/src/main/java/com/unfbx/chatgpt/utils/TikTokensUtil.java b/src/main/java/com/unfbx/chatgpt/utils/TikTokensUtil.java
index e615dde..7e6f3ae 100644
--- a/src/main/java/com/unfbx/chatgpt/utils/TikTokensUtil.java
+++ b/src/main/java/com/unfbx/chatgpt/utils/TikTokensUtil.java
@@ -1,12 +1,14 @@
package com.unfbx.chatgpt.utils;
import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
import com.knuddels.jtokkit.Encodings;
import com.knuddels.jtokkit.api.Encoding;
import com.knuddels.jtokkit.api.EncodingRegistry;
import com.knuddels.jtokkit.api.EncodingType;
import com.knuddels.jtokkit.api.ModelType;
import com.unfbx.chatgpt.entity.chat.ChatCompletion;
+import com.unfbx.chatgpt.entity.chat.FunctionCall;
import com.unfbx.chatgpt.entity.chat.Message;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
@@ -35,9 +37,14 @@ public class TikTokensUtil {
modelMap.put(modelType.getName(), registry.getEncodingForModel(modelType));
}
modelMap.put(ChatCompletion.Model.GPT_3_5_TURBO_0301.getName(), registry.getEncodingForModel(ModelType.GPT_3_5_TURBO));
+ modelMap.put(ChatCompletion.Model.GPT_3_5_TURBO_0613.getName(), registry.getEncodingForModel(ModelType.GPT_3_5_TURBO));
+ modelMap.put(ChatCompletion.Model.GPT_3_5_TURBO_16K.getName(), registry.getEncodingForModel(ModelType.GPT_3_5_TURBO));
+ modelMap.put(ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName(), registry.getEncodingForModel(ModelType.GPT_3_5_TURBO));
modelMap.put(ChatCompletion.Model.GPT_4_32K.getName(), registry.getEncodingForModel(ModelType.GPT_4));
modelMap.put(ChatCompletion.Model.GPT_4_32K_0314.getName(), registry.getEncodingForModel(ModelType.GPT_4));
modelMap.put(ChatCompletion.Model.GPT_4_0314.getName(), registry.getEncodingForModel(ModelType.GPT_4));
+ modelMap.put(ChatCompletion.Model.GPT_4_0613.getName(), registry.getEncodingForModel(ModelType.GPT_4));
+ modelMap.put(ChatCompletion.Model.GPT_4_32K_0613.getName(), registry.getEncodingForModel(ModelType.GPT_4));
}
/**
@@ -179,15 +186,29 @@ public static int tokens(@NotNull String modelName, @NotNull List messa
Encoding encoding = getEncoding(modelName);
int tokensPerMessage = 0;
int tokensPerName = 0;
- //3.5统一处理
- if (modelName.equals("gpt-3.5-turbo-0301") || modelName.equals("gpt-3.5-turbo")) {
+ if (modelName.equals(ChatCompletion.Model.GPT_3_5_TURBO_0613.getName())
+ || modelName.equals(ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName())
+ || modelName.equals(ChatCompletion.Model.GPT_4_0314.getName())
+ || modelName.equals(ChatCompletion.Model.GPT_4_32K_0314.getName())
+ || modelName.equals(ChatCompletion.Model.GPT_4_0613.getName())
+ || modelName.equals(ChatCompletion.Model.GPT_4_32K_0613.getName())
+ ) {
+ tokensPerMessage = 3;
+ tokensPerName = 1;
+ }else if(modelName.equals(ChatCompletion.Model.GPT_3_5_TURBO_0301.getName())){
tokensPerMessage = 4;
tokensPerName = -1;
- }
- //4.0统一处理
- if (modelName.equals("gpt-4") || modelName.equals("gpt-4-0314")) {
+ }else if(modelName.contains(ChatCompletion.Model.GPT_3_5_TURBO.getName())){
+ //"gpt-3.5-turbo" in model:
+ log.warn("Warning: gpt-3.5-turbo may update over time. Returning num tokens assuming gpt-3.5-turbo-0613.");
+ tokensPerMessage = 3;
+ tokensPerName = 1;
+ }else if(modelName.contains(ChatCompletion.Model.GPT_4.getName())){
+ log.warn("Warning: gpt-4 may update over time. Returning num tokens assuming gpt-4-0613.");
tokensPerMessage = 3;
tokensPerName = 1;
+ }else {
+ log.warn("不支持的model {}. See https://github.com/openai/openai-python/blob/main/chatml.md 更多信息.",modelName);
}
int sum = 0;
for (Message msg : messages) {
@@ -195,6 +216,8 @@ public static int tokens(@NotNull String modelName, @NotNull List messa
sum += tokens(encoding, msg.getContent());
sum += tokens(encoding, msg.getRole());
sum += tokens(encoding, msg.getName());
+ FunctionCall functionCall = msg.getFunctionCall();
+ sum += Objects.isNull(functionCall) ? 0 : tokens(encoding, functionCall.toString());
if (StrUtil.isNotBlank(msg.getName())) {
sum += tokensPerName;
}
@@ -206,9 +229,9 @@ public static int tokens(@NotNull String modelName, @NotNull List messa
/**
* 通过模型名称和encoded编码数组,反推字符串文本
*
- * @param modelName
- * @param encoded
- * @return
+ * @param modelName 模型名
+ * @param encoded 编码数组
+ * @return 返回源文本
*/
public static String decode(@NotNull String modelName, @NotNull List encoded) {
Encoding enc = getEncoding(modelName);
@@ -219,17 +242,25 @@ public static String decode(@NotNull String modelName, @NotNull List en
/**
* 获取modelType
*
- * @param name
- * @return
+ * @param name 模型名称
+ * @return ModelType
*/
public static ModelType getModelTypeByName(String name) {
- if (ChatCompletion.Model.GPT_3_5_TURBO_0301.getName().equals(name)) {
+ if (
+ ChatCompletion.Model.GPT_3_5_TURBO_0301.getName().equals(name) ||
+ ChatCompletion.Model.GPT_3_5_TURBO_0613.getName().equals(name) ||
+ ChatCompletion.Model.GPT_3_5_TURBO_16K.getName().equals(name) ||
+ ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName().equals(name)
+ ) {
return ModelType.GPT_3_5_TURBO;
}
if (ChatCompletion.Model.GPT_4.getName().equals(name)
|| ChatCompletion.Model.GPT_4_32K.getName().equals(name)
|| ChatCompletion.Model.GPT_4_32K_0314.getName().equals(name)
- || ChatCompletion.Model.GPT_4_0314.getName().equals(name)) {
+ || ChatCompletion.Model.GPT_4_0314.getName().equals(name)
+ || ChatCompletion.Model.GPT_4_0613.getName().equals(name)
+ || ChatCompletion.Model.GPT_4_32K_0613.getName().equals(name)
+ ) {
return ModelType.GPT_4;
}
diff --git a/src/test/java/com/unfbx/chatgpt/ConsoleEventSourceListenerV2.java b/src/test/java/com/unfbx/chatgpt/ConsoleEventSourceListenerV2.java
new file mode 100644
index 0000000..3a52374
--- /dev/null
+++ b/src/test/java/com/unfbx/chatgpt/ConsoleEventSourceListenerV2.java
@@ -0,0 +1,72 @@
+package com.unfbx.chatgpt;
+
+import cn.hutool.json.JSONUtil;
+import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse;
+import lombok.Getter;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+import okhttp3.sse.EventSource;
+import okhttp3.sse.EventSourceListener;
+
+import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * 描述: sse
+ *
+ * @author https:www.unfbx.com
+ * 2023-06-15
+ */
+@Slf4j
+public class ConsoleEventSourceListenerV2 extends EventSourceListener {
+ @Getter
+ String args = "";
+ CountDownLatch countDownLatch;
+
+ public ConsoleEventSourceListenerV2(CountDownLatch countDownLatch) {
+ this.countDownLatch = countDownLatch;
+ }
+
+ @Override
+ public void onOpen(EventSource eventSource, Response response) {
+ log.info("OpenAI建立sse连接...");
+ }
+
+ @Override
+ public void onEvent(EventSource eventSource, String id, String type, String data) {
+ log.info("OpenAI返回数据:{}", data);
+ if (data.equals("[DONE]")) {
+ log.info("OpenAI返回数据结束了");
+ countDownLatch.countDown();
+ return;
+ }
+ ChatCompletionResponse chatCompletionResponse = JSONUtil.toBean(data, ChatCompletionResponse.class);
+ if(Objects.nonNull(chatCompletionResponse.getChoices().get(0).getDelta().getFunctionCall())){
+ args += chatCompletionResponse.getChoices().get(0).getDelta().getFunctionCall().getArguments();
+ }
+ }
+
+ @Override
+ public void onClosed(EventSource eventSource) {
+ log.info("OpenAI关闭sse连接...");
+ }
+
+ @SneakyThrows
+ @Override
+ public void onFailure(EventSource eventSource, Throwable t, Response response) {
+ if(Objects.isNull(response)){
+ log.error("OpenAI sse连接异常:{}", t);
+ eventSource.cancel();
+ return;
+ }
+ ResponseBody body = response.body();
+ if (Objects.nonNull(body)) {
+ log.error("OpenAI sse连接异常data:{},异常:{}", body.string(), t);
+ } else {
+ log.error("OpenAI sse连接异常data:{},异常:{}", response, t);
+ }
+ eventSource.cancel();
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/unfbx/chatgpt/OpenAiClientFunctionTest.java b/src/test/java/com/unfbx/chatgpt/OpenAiClientFunctionTest.java
new file mode 100644
index 0000000..527e11b
--- /dev/null
+++ b/src/test/java/com/unfbx/chatgpt/OpenAiClientFunctionTest.java
@@ -0,0 +1,294 @@
+package com.unfbx.chatgpt;
+
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.unfbx.chatgpt.entity.chat.*;
+import com.unfbx.chatgpt.function.KeyRandomStrategy;
+import com.unfbx.chatgpt.interceptor.DynamicKeyOpenAiAuthInterceptor;
+import com.unfbx.chatgpt.interceptor.OpenAILogger;
+import com.unfbx.chatgpt.interceptor.OpenAiResponseInterceptor;
+import com.unfbx.chatgpt.sse.ConsoleEventSourceListener;
+import lombok.Builder;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.OkHttpClient;
+import okhttp3.logging.HttpLoggingInterceptor;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 描述: 测试类
+ *
+ * @author https:www.unfbx.com
+ * 2023-06-14
+ */
+@Slf4j
+public class OpenAiClientFunctionTest {
+
+ private OpenAiClient openAiClient;
+ private OpenAiStreamClient openAiStreamClient;
+
+ @Before
+ public void before() {
+ //可以为null
+ Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890));
+ HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger());
+ //!!!!千万别再生产或者测试环境打开BODY级别日志!!!!
+ //!!!生产或者测试环境建议设置为这三种级别:NONE,BASIC,HEADERS,!!!
+ httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
+ OkHttpClient okHttpClient = new OkHttpClient
+ .Builder()
+// .proxy(proxy)
+ .addInterceptor(httpLoggingInterceptor)
+ .addInterceptor(new OpenAiResponseInterceptor())
+ .connectTimeout(10, TimeUnit.SECONDS)
+ .writeTimeout(30, TimeUnit.SECONDS)
+ .readTimeout(30, TimeUnit.SECONDS)
+ .build();
+ openAiClient = OpenAiClient.builder()
+ //支持多key传入,请求时候随机选择
+ .apiKey(Arrays.asList("sk-******************"))
+ //自定义key的获取策略:默认KeyRandomStrategy
+ .keyStrategy(new KeyRandomStrategy())
+ .authInterceptor(new DynamicKeyOpenAiAuthInterceptor())
+ .okHttpClient(okHttpClient)
+ //自己做了代理就传代理地址,没有可不不传,(关注公众号回复:openai ,获取免费的测试代理地址)
+ .apiHost("https://dgr.life/")
+ .build();
+
+ openAiStreamClient = OpenAiStreamClient.builder()
+ //支持多key传入,请求时候随机选择
+ .apiKey(Arrays.asList("sk-*********************"))
+ //自定义key的获取策略:默认KeyRandomStrategy
+ .keyStrategy(new KeyRandomStrategy())
+ .authInterceptor(new DynamicKeyOpenAiAuthInterceptor())
+ .okHttpClient(okHttpClient)
+ //自己做了代理就传代理地址,没有可不不传,(关注公众号回复:openai ,获取免费的测试代理地址)
+ .apiHost("https://dgr.life/")
+ .build();
+ }
+
+ /**
+ * 阻塞输出日志如下:
+ *
+ * [main] INFO com.unfbx.chatgpt.OpenAiClientFunctionTest - 自定义的方法返回值:词语:苹果
+ *
+ * 用途:苹果是一种水果,具有多种用途。以下是苹果的几种常见用途:
+ *
+ * 1. 直接吃:苹果可以直接食用,具有清爽的口感和丰富的营养成分,是一种健康的零食选择。
+ *
+ * 2. 做沙拉:苹果可以切成块状或丝状,加入其他蔬菜和调味料,制作成沙拉。苹果的甜脆口感可以为沙拉增添口感和风味。
+ *
+ * 3. 售卖:苹果是一种常见的水果,可以被商家售卖。人们可以购买苹果作为食物或礼物,满足自己或他人的需求。
+ *
+ * 总之,苹果是一种多功能的水果,可以直接食用,也可以用于制作沙拉,同时也是一种常见的商业商品。
+ */
+ @Test
+ public void chatFunction() {
+
+ //模型:GPT_3_5_TURBO_16K_0613
+ Message message = Message.builder().role(Message.Role.USER).content("给我输出一个长度为2的中文词语,并解释下词语对应物品的用途").build();
+ //属性一
+ JSONObject wordLength = new JSONObject();
+ wordLength.putOpt("type", "number");
+ wordLength.putOpt("description", "词语的长度");
+ //属性二
+ JSONObject language = new JSONObject();
+ language.putOpt("type", "string");
+ language.putOpt("enum", Arrays.asList("zh", "en"));
+ language.putOpt("description", "语言类型,例如:zh代表中文、en代表英语");
+ //参数
+ JSONObject properties = new JSONObject();
+ properties.putOpt("wordLength", wordLength);
+ properties.putOpt("language", language);
+ Parameters parameters = Parameters.builder()
+ .type("object")
+ .properties(properties)
+ .required(Arrays.asList("wordLength")).build();
+ Functions functions = Functions.builder()
+ .name("getOneWord")
+ .description("获取一个指定长度和语言类型的词语")
+ .parameters(parameters)
+ .build();
+
+ ChatCompletion chatCompletion = ChatCompletion
+ .builder()
+ .messages(Arrays.asList(message))
+ .functions(Arrays.asList(functions))
+ .functionCall("auto")
+ .model(ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName())
+ .build();
+ ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion);
+
+ ChatChoice chatChoice = chatCompletionResponse.getChoices().get(0);
+ log.info("构造的方法值:{}", chatChoice.getMessage().getFunctionCall());
+ log.info("构造的方法名称:{}", chatChoice.getMessage().getFunctionCall().getName());
+ log.info("构造的方法参数:{}", chatChoice.getMessage().getFunctionCall().getArguments());
+ WordParam wordParam = JSONUtil.toBean(chatChoice.getMessage().getFunctionCall().getArguments(), WordParam.class);
+ String oneWord = getOneWord(wordParam);
+
+ FunctionCall functionCall = FunctionCall.builder()
+ .arguments(chatChoice.getMessage().getFunctionCall().getArguments())
+ .name("getOneWord")
+ .build();
+ Message message2 = Message.builder().role(Message.Role.ASSISTANT).content("方法参数").functionCall(functionCall).build();
+ String content
+ = "{ " +
+ "\"wordLength\": \"3\", " +
+ "\"language\": \"zh\", " +
+ "\"word\": \"" + oneWord + "\"," +
+ "\"用途\": [\"直接吃\", \"做沙拉\", \"售卖\"]" +
+ "}";
+ Message message3 = Message.builder().role(Message.Role.FUNCTION).name("getOneWord").content(content).build();
+ List messageList = Arrays.asList(message, message2, message3);
+ ChatCompletion chatCompletionV2 = ChatCompletion
+ .builder()
+ .messages(messageList)
+ .model(ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName())
+ .build();
+ ChatCompletionResponse chatCompletionResponseV2 = openAiClient.chatCompletion(chatCompletionV2);
+ log.info("自定义的方法返回值:{}",chatCompletionResponseV2.getChoices().get(0).getMessage().getContent());
+ }
+
+
+ /**
+ * 流式输出最后输出日志如下
+ * .........省略省略省略省略省略............
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:{"id":"chatcmpl-7RXBSbHZPGCbiV9uO9iPlgoZ56t9y","object":"chat.completion.chunk","created":1686796770,"model":"gpt-3.5-turbo-16k-0613","choices":[{"index":0,"delta":{"content":"、"},"finish_reason":null}]}
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:{"id":"chatcmpl-7RXBSbHZPGCbiV9uO9iPlgoZ56t9y","object":"chat.completion.chunk","created":1686796770,"model":"gpt-3.5-turbo-16k-0613","choices":[{"index":0,"delta":{"content":"水"},"finish_reason":null}]}
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:{"id":"chatcmpl-7RXBSbHZPGCbiV9uO9iPlgoZ56t9y","object":"chat.completion.chunk","created":1686796770,"model":"gpt-3.5-turbo-16k-0613","choices":[{"index":0,"delta":{"content":"果"},"finish_reason":null}]}
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:{"id":"chatcmpl-7RXBSbHZPGCbiV9uO9iPlgoZ56t9y","object":"chat.completion.chunk","created":1686796770,"model":"gpt-3.5-turbo-16k-0613","choices":[{"index":0,"delta":{"content":"摊"},"finish_reason":null}]}
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:{"id":"chatcmpl-7RXBSbHZPGCbiV9uO9iPlgoZ56t9y","object":"chat.completion.chunk","created":1686796770,"model":"gpt-3.5-turbo-16k-0613","choices":[{"index":0,"delta":{"content":"等"},"finish_reason":null}]}
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:{"id":"chatcmpl-7RXBSbHZPGCbiV9uO9iPlgoZ56t9y","object":"chat.completion.chunk","created":1686796770,"model":"gpt-3.5-turbo-16k-0613","choices":[{"index":0,"delta":{"content":"渠"},"finish_reason":null}]}
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:{"id":"chatcmpl-7RXBSbHZPGCbiV9uO9iPlgoZ56t9y","object":"chat.completion.chunk","created":1686796770,"model":"gpt-3.5-turbo-16k-0613","choices":[{"index":0,"delta":{"content":"道"},"finish_reason":null}]}
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:{"id":"chatcmpl-7RXBSbHZPGCbiV9uO9iPlgoZ56t9y","object":"chat.completion.chunk","created":1686796770,"model":"gpt-3.5-turbo-16k-0613","choices":[{"index":0,"delta":{"content":"进行"},"finish_reason":null}]}
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:{"id":"chatcmpl-7RXBSbHZPGCbiV9uO9iPlgoZ56t9y","object":"chat.completion.chunk","created":1686796770,"model":"gpt-3.5-turbo-16k-0613","choices":[{"index":0,"delta":{"content":"销"},"finish_reason":null}]}
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:{"id":"chatcmpl-7RXBSbHZPGCbiV9uO9iPlgoZ56t9y","object":"chat.completion.chunk","created":1686796770,"model":"gpt-3.5-turbo-16k-0613","choices":[{"index":0,"delta":{"content":"售"},"finish_reason":null}]}
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:{"id":"chatcmpl-7RXBSbHZPGCbiV9uO9iPlgoZ56t9y","object":"chat.completion.chunk","created":1686796770,"model":"gpt-3.5-turbo-16k-0613","choices":[{"index":0,"delta":{"content":"。"},"finish_reason":null}]}
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:{"id":"chatcmpl-7RXBSbHZPGCbiV9uO9iPlgoZ56t9y","object":"chat.completion.chunk","created":1686796770,"model":"gpt-3.5-turbo-16k-0613","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据:[DONE]
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI返回数据结束了
+ * [OkHttp https://dgr.life/...] INFO com.unfbx.chatgpt.ConsoleEventSourceListenerV2 - OpenAI关闭sse连接...
+ */
+ @Test
+ public void streamChatFunction() {
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+
+ ConsoleEventSourceListenerV2 eventSourceListener = new ConsoleEventSourceListenerV2(countDownLatch);
+
+ //模型:GPT_3_5_TURBO_16K_0613
+ Message message = Message.builder().role(Message.Role.USER).content("给我输出一个长度为2的中文词语,并解释下词语对应物品的用途").build();
+ //属性一
+ JSONObject wordLength = new JSONObject();
+ wordLength.putOpt("type", "number");
+ wordLength.putOpt("description", "词语的长度");
+ //属性二
+ JSONObject language = new JSONObject();
+ language.putOpt("type", "string");
+ language.putOpt("enum", Arrays.asList("zh", "en"));
+ language.putOpt("description", "语言类型,例如:zh代表中文、en代表英语");
+ //参数
+ JSONObject properties = new JSONObject();
+ properties.putOpt("wordLength", wordLength);
+ properties.putOpt("language", language);
+ Parameters parameters = Parameters.builder()
+ .type("object")
+ .properties(properties)
+ .required(Arrays.asList("wordLength")).build();
+ Functions functions = Functions.builder()
+ .name("getOneWord")
+ .description("获取一个指定长度和语言类型的词语")
+ .parameters(parameters)
+ .build();
+
+ ChatCompletion chatCompletion = ChatCompletion
+ .builder()
+ .messages(Arrays.asList(message))
+ .functions(Arrays.asList(functions))
+ .functionCall("auto")
+ .model(ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName())
+ .build();
+ openAiStreamClient.streamChatCompletion(chatCompletion, eventSourceListener);
+ try {
+ countDownLatch.await();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ String args = eventSourceListener.getArgs();
+ log.info("构造的方法参数:{}", args);
+ WordParam wordParam = JSONUtil.toBean(args, WordParam.class);
+ String oneWord = getOneWord(wordParam);
+
+ FunctionCall functionCall = FunctionCall.builder()
+ .arguments(args)
+ .name("getOneWord")
+ .build();
+ Message message2 = Message.builder().role(Message.Role.ASSISTANT).content("方法参数").functionCall(functionCall).build();
+ String content
+ = "{ " +
+ "\"wordLength\": \"3\", " +
+ "\"language\": \"zh\", " +
+ "\"word\": \"" + oneWord + "\"," +
+ "\"用途\": [\"直接吃\", \"做沙拉\", \"售卖\"]" +
+ "}";
+ Message message3 = Message.builder().role(Message.Role.FUNCTION).name("getOneWord").content(content).build();
+ List messageList = Arrays.asList(message, message2, message3);
+ ChatCompletion chatCompletionV2 = ChatCompletion
+ .builder()
+ .messages(messageList)
+ .model(ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName())
+ .build();
+ CountDownLatch countDownLatch1 = new CountDownLatch(1);
+ openAiStreamClient.streamChatCompletion(chatCompletionV2, new ConsoleEventSourceListenerV2(countDownLatch));
+ try {
+ countDownLatch1.await();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 获取一个词语
+ * @param wordParam
+ * @return
+ */
+ public String getOneWord(WordParam wordParam) {
+
+ List zh = Arrays.asList("大香蕉", "哈密瓜", "苹果");
+ List en = Arrays.asList("apple", "banana", "cantaloupe");
+ if (wordParam.getLanguage().equals("zh")) {
+ for (String e : zh) {
+ if (e.length() == wordParam.getWordLength()) {
+ return e;
+ }
+ }
+ }
+ if (wordParam.getLanguage().equals("en")) {
+ for (String e : en) {
+ if (e.length() == wordParam.getWordLength()) {
+ return e;
+ }
+ }
+ }
+ return "西瓜";
+ }
+
+ @Test
+ public void testInput() {
+ System.out.println(getOneWord(WordParam.builder().wordLength(2).language("zh").build()));
+ }
+
+ @Data
+ @Builder
+ static class WordParam {
+ private int wordLength;
+ @Builder.Default
+ private String language = "zh";
+ }
+}