diff --git a/README.md b/README.md index 330e37b..09ac34e 100644 --- a/README.md +++ b/README.md @@ -64,11 +64,11 @@ WebSocket参考:[OpenAIWebSocketEventSourceListener](https://github.com/Grt122 - 支持自定义ApiKey的获取策略 - 支持余额查询 - 支持个人账户信息查询 -- 支持GPT3、GPT3.5、GPT4.0 +- 支持GPT3、GPT3.5、GPT4.0、GPT3.5—0614、GPT4.0—0614... - 支持全部OpenAI的Api # 📑 更新日志 -- [ ] 1.0.14 升级支持最新版0614模型,支持function-calling +- [x] 1.0.14 升级支持最新版Gpt-3.5—0614、Gpt-4.0—0614等模型, 支持function-calling完整使用案例参考:[OpenAiClientFunctionTest](https://github.com/Grt1228/chatgpt-java/blob/1.0.14/src/test/java/com/unfbx/chatgpt/OpenAiClientFunctionTest.java) - [x] 1.0.13 支持当key异常(失效、过期、封禁)时,自定义动态处理key,参考实现[DynamicKeyOpenAiAuthInterceptor](https://github.com/Grt1228/chatgpt-java/blob/main/src/main/java/com/unfbx/chatgpt/interceptor/DynamicKeyOpenAiAuthInterceptor.java) ,支持key异常时的告警处理(钉钉、飞书、email、企业微信等等需要自定义开发) - [x] 1.0.12 tokens计算优化、删除模型接口修改、语音接口更新支持官方最新参数 - [x] 1.0.11 增加新的余额查询接口参考:[OpenAiClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiClientTest.java) 和[OpenAiStreamClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiStreamClientTest.java) ,修复tokens计算慢的问题, @@ -86,9 +86,10 @@ WebSocket参考:[OpenAIWebSocketEventSourceListener](https://github.com/Grt122 # 🚀 快速开始 本项目支持**默认输出**和**流式输出**。完整SDK测试案例参考: -SDK测试案例 | Tokens测试案例 | ----|---| -[OpenAiClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiClientTest.java) 和[OpenAiStreamClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiStreamClientTest.java) | Tokens计算参考:[TikTokensTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/TikTokensTest.java)| + +SDK测试案例 | Tokens计算测试案例 | 完整Function-Call调用案例 +---| --- | --- +[OpenAiClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiClientTest.java) 和[OpenAiStreamClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiStreamClientTest.java) | Tokens计算参考:[TikTokensTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/TikTokensTest.java) | [OpenAiClientFunctionTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiClientFunctionTest.java) ## 方式一 @@ -97,7 +98,7 @@ SDK测试案例 | Tokens测试案例 | com.unfbx chatgpt-java - 1.0.13 + 1.0.14-beta1 ``` ### 2、流式客户端使用示例: diff --git a/README_EN.md b/README_EN.md index 96bbe48..a279c99 100644 --- a/README_EN.md +++ b/README_EN.md @@ -61,11 +61,11 @@ WebSocket Reference:[OpenAIWebSocketEventSourceListener](https://github.com/Gr - Supports customizing the key acquisition strategy. - Supports balance inquiry. - Supports personal account information inquiry. -- Supports GPT3, GPT3.5, GPT4.0. +- Supports GPT3, GPT3.5, GPT4.0, GPT3.5—0614, GPT4.0—0614... - Supports all OpenAI APIs. # 📑 Update Log -- [ ] 1.0.14 Upgrade to support the latest version 0614 model, support function-calling +- [x] 1.0.14 Upgrade to support the latest version gpt-3.5—0614、gpt-4.0—0614 models, support function-calling full test e.g.:[OpenAiClientFunctionTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiClientFunctionTest.java) - [x] 1.0.13 Added support for custom handling of key exceptions (invalid, expired, blocked) with the implementation reference [DynamicKeyOpenAiAuthInterceptor](https://github.com/Grt1228/chatgpt-java/blob/main/src/main/java/com/unfbx/chatgpt/interceptor/DynamicKeyOpenAiAuthInterceptor.java). Also added support for alerting on key exceptions (DingTalk, Feishu, email, WeChat Enterprise, etc.), which requires custom development. - [x] 1.0.12 Optimized token calculation, modified delete model interface, and updated speech interface to support the latest official parameters. - [x] 1.0.11 Added new balance query interface with reference to [OpenAiClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiClientTest.java) and [OpenAiStreamClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiStreamClientTest.java). Fixed slow token calculation issue. @@ -85,9 +85,9 @@ WebSocket Reference:[OpenAIWebSocketEventSourceListener](https://github.com/Gr This project supports both **default output** and **streaming output**. For a complete SDK test case, see: -SDK Test Cases | Token Test Cases | ----|---| -[OpenAiClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiClientTest.java) and [OpenAiStreamClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiStreamClientTest.java) | Token calculation reference: [TikTokensTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/TikTokensTest.java)| +SDK Test Cases | TikToken Test Cases | Full Function Call Test Cases +---|---|---| +[OpenAiClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiClientTest.java) and [OpenAiStreamClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiStreamClientTest.java) | Token calculation reference: [TikTokensTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/TikTokensTest.java) | [OpenAiClientFunctionTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiClientFunctionTest.java) ## Method 1 @@ -96,7 +96,7 @@ SDK Test Cases | Token Test Cases | com.unfbx chatgpt-java - 1.0.13 + 1.0.14 ``` ### 2. Streaming client usage example: diff --git a/Tokens_README.md b/Tokens_README.md index e0f5787..2bcb198 100644 --- a/Tokens_README.md +++ b/Tokens_README.md @@ -2,7 +2,7 @@ chatgpt-java 更新到1.0.10支持Tokens计算,增加[TikTokensUtil](https://github.com/Grt1228/chatgpt-java/blob/main/src/main/java/com/unfbx/chatgpt/utils/TikTokensUtil.java) 工具类. ## tokens计算说明 -openai 的tokens计算规则适合模型先关的,不同的模型计算方法是不一样的。大致的表格如下: +openai 的tokens计算规则和模型相关的,不同的模型计算方法是不一样的。大致的表格如下: ## 关于流式返回 流式返回的数据,返回行数-2=返回tokens @@ -28,7 +28,7 @@ openai 的tokens计算规则适合模型先关的,不同的模型计算方法 ## 使用示例 完整使用示例请参考:[TikTokensTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/TikTokensTest.java) -结合chat模型使用示例: +### 结合chat模型使用示例: 完整示例参考:[OpenAiClientTest](https://github.com/Grt1228/chatgpt-java/blob/main/src/test/java/com/unfbx/chatgpt/OpenAiClientTest.java) ``` public void chatTokensTest() { @@ -51,7 +51,7 @@ openai 的tokens计算规则适合模型先关的,不同的模型计算方法 log.info("Open AI 官方计算的返回的tokens数{}", chatCompletionResponse.getUsage().getCompletionTokens()); } ``` -单独使用示例: +### 单独使用示例: ```java public class TikTokensTest { String text; diff --git a/pom.xml b/pom.xml index 20ab3f5..3dbd707 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.unfbx chatgpt-java - 1.0.13 + 1.0.14 chatgpt-java OpenAI Java SDK, OpenAI Api for Java. ChatGPT Java SDK . https://www.unfbx.com @@ -115,7 +115,7 @@ com.knuddels jtokkit - 0.2.0 + 0.5.0 diff --git a/src/main/java/com/unfbx/chatgpt/OpenAiApi.java b/src/main/java/com/unfbx/chatgpt/OpenAiApi.java index e48999f..60114a5 100644 --- a/src/main/java/com/unfbx/chatgpt/OpenAiApi.java +++ b/src/main/java/com/unfbx/chatgpt/OpenAiApi.java @@ -55,7 +55,7 @@ public interface OpenAiApi { /** * models 返回的数据id * - * @param id + * @param id 模型主键 * @return Single Model */ @GET("v1/models/{id}") @@ -314,7 +314,7 @@ Single speechToTextTranslations(@Part MultipartBody.Part file, /** * 账户信息查询:里面包含总金额(美元)等信息 * - * @return + * @return 账户信息 */ @GET("v1/dashboard/billing/subscription") Single subscription(); diff --git a/src/main/java/com/unfbx/chatgpt/OpenAiClient.java b/src/main/java/com/unfbx/chatgpt/OpenAiClient.java index f2194c3..e2b0dc2 100644 --- a/src/main/java/com/unfbx/chatgpt/OpenAiClient.java +++ b/src/main/java/com/unfbx/chatgpt/OpenAiClient.java @@ -102,7 +102,7 @@ public class OpenAiClient { /** * 构造器 * - * @return + * @return OpenAiClient.Builder */ public static OpenAiClient.Builder builder() { return new OpenAiClient.Builder(); @@ -189,8 +189,8 @@ public List models() { /** * openAi模型详细信息 * - * @param id - * @return Model + * @param id 模型主键 + * @return Model 模型类 */ public Model model(String id) { if (Objects.isNull(id) || "".equals(id)) { @@ -240,7 +240,7 @@ public EditResponse edit(Edit edit) { /** * 根据描述生成图片 * - * @param prompt + * @param prompt 描述信息 * @return ImageResponse */ public ImageResponse genImages(String prompt) { @@ -407,7 +407,7 @@ private void checkImageSize(java.io.File image) { /** * 向量计算:单文本 * - * @param input + * @param input 单文本 * @return EmbeddingResponse */ public EmbeddingResponse embeddings(String input) { @@ -480,7 +480,7 @@ public UploadFileResponse uploadFile(String purpose, java.io.File file) { /** * 上传文件 * - * @param file + * @param file 文件 * @return UploadFileResponse */ public UploadFileResponse uploadFile(java.io.File file) { @@ -538,7 +538,7 @@ public ModerationResponse moderations(List input) { /** * 文本审核 * - * @param moderation + * @param moderation 审核参数 * @return ModerationResponse */ public ModerationResponse moderations(Moderation moderation) { @@ -592,7 +592,7 @@ public FineTuneResponse retrieveFineTune(String fineTuneId) { /** * 取消微调作业 * - * @param fineTuneId + * @param fineTuneId 主键 * @return FineTuneResponse */ public FineTuneResponse cancelFineTune(String fineTuneId) { @@ -615,7 +615,7 @@ public List fineTuneEvents(String fineTuneId) { * 删除微调作业模型 * Delete a fine-tuned model. You must have the Owner role in your organization. * - * @param model + * @param model 模型名称 * @return FineTuneDeleteResponse */ public FineTuneDeleteResponse deleteFineTuneModel(String model) { @@ -771,7 +771,7 @@ private void checkSpeechFileSize(java.io.File file) { * ## 官方已经禁止使用此api * OpenAi账户余额查询 * - * @return + * @return 余额 * @see #subscription() * @see #billingUsage(LocalDate, LocalDate) */ diff --git a/src/main/java/com/unfbx/chatgpt/OpenAiStreamClient.java b/src/main/java/com/unfbx/chatgpt/OpenAiStreamClient.java index 3b96ec4..2c02422 100644 --- a/src/main/java/com/unfbx/chatgpt/OpenAiStreamClient.java +++ b/src/main/java/com/unfbx/chatgpt/OpenAiStreamClient.java @@ -310,7 +310,7 @@ public Subscription subscription() { * * @param starDate 开始时间 * @param endDate 结束时间 - * @return + * @return 消耗金额信息 */ public BillingUsage billingUsage(@NotNull LocalDate starDate, @NotNull LocalDate endDate) { Single billingUsage = this.openAiApi.billingUsage(starDate, endDate); @@ -320,7 +320,7 @@ public BillingUsage billingUsage(@NotNull LocalDate starDate, @NotNull LocalDate /** * 构造 * - * @return + * @return Builder */ public static OpenAiStreamClient.Builder builder() { return new OpenAiStreamClient.Builder(); @@ -361,7 +361,7 @@ public Builder apiKey(@NotNull List val) { /** * @param val api请求地址,结尾处有斜杠 - * @return + * @return Builder * @see com.unfbx.chatgpt.constant.OpenAIConst */ public Builder apiHost(String val) { diff --git a/src/main/java/com/unfbx/chatgpt/entity/billing/BillingUsage.java b/src/main/java/com/unfbx/chatgpt/entity/billing/BillingUsage.java index 52be352..125a031 100644 --- a/src/main/java/com/unfbx/chatgpt/entity/billing/BillingUsage.java +++ b/src/main/java/com/unfbx/chatgpt/entity/billing/BillingUsage.java @@ -1,5 +1,6 @@ package com.unfbx.chatgpt.entity.billing; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @@ -13,6 +14,7 @@ * @since 2023-04-08 */ @Data +@JsonIgnoreProperties(ignoreUnknown = true) public class BillingUsage { @JsonProperty("object") diff --git a/src/main/java/com/unfbx/chatgpt/entity/billing/CreditGrantsResponse.java b/src/main/java/com/unfbx/chatgpt/entity/billing/CreditGrantsResponse.java index 4c004c8..a28ac97 100644 --- a/src/main/java/com/unfbx/chatgpt/entity/billing/CreditGrantsResponse.java +++ b/src/main/java/com/unfbx/chatgpt/entity/billing/CreditGrantsResponse.java @@ -1,5 +1,6 @@ package com.unfbx.chatgpt.entity.billing; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @@ -13,6 +14,7 @@ * @since 2023-03-18 */ @Data +@JsonIgnoreProperties(ignoreUnknown = true) public class CreditGrantsResponse implements Serializable { private String object; /** diff --git a/src/main/java/com/unfbx/chatgpt/entity/billing/DailyCost.java b/src/main/java/com/unfbx/chatgpt/entity/billing/DailyCost.java index 1c28dd5..14112a6 100644 --- a/src/main/java/com/unfbx/chatgpt/entity/billing/DailyCost.java +++ b/src/main/java/com/unfbx/chatgpt/entity/billing/DailyCost.java @@ -1,5 +1,6 @@ package com.unfbx.chatgpt.entity.billing; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @@ -12,6 +13,7 @@ * @since 2023-04-08 */ @Data +@JsonIgnoreProperties(ignoreUnknown = true) public class DailyCost { /** * 时间戳 diff --git a/src/main/java/com/unfbx/chatgpt/entity/billing/Datum.java b/src/main/java/com/unfbx/chatgpt/entity/billing/Datum.java index 2593b48..72c997f 100644 --- a/src/main/java/com/unfbx/chatgpt/entity/billing/Datum.java +++ b/src/main/java/com/unfbx/chatgpt/entity/billing/Datum.java @@ -1,5 +1,6 @@ package com.unfbx.chatgpt.entity.billing; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @@ -12,6 +13,7 @@ * @since 2023-03-18 */ @Data +@JsonIgnoreProperties(ignoreUnknown = true) public class Datum { private String object; private String id; diff --git a/src/main/java/com/unfbx/chatgpt/entity/billing/Grants.java b/src/main/java/com/unfbx/chatgpt/entity/billing/Grants.java index 9eb836d..45202ac 100644 --- a/src/main/java/com/unfbx/chatgpt/entity/billing/Grants.java +++ b/src/main/java/com/unfbx/chatgpt/entity/billing/Grants.java @@ -1,5 +1,6 @@ package com.unfbx.chatgpt.entity.billing; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @@ -12,6 +13,7 @@ * @since 2023-03-18 */ @Data +@JsonIgnoreProperties(ignoreUnknown = true) public class Grants { private String object; @JsonProperty("data") diff --git a/src/main/java/com/unfbx/chatgpt/entity/billing/LineItem.java b/src/main/java/com/unfbx/chatgpt/entity/billing/LineItem.java index 7f78ea6..da2029f 100644 --- a/src/main/java/com/unfbx/chatgpt/entity/billing/LineItem.java +++ b/src/main/java/com/unfbx/chatgpt/entity/billing/LineItem.java @@ -1,5 +1,6 @@ package com.unfbx.chatgpt.entity.billing; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; import java.math.BigDecimal; @@ -11,6 +12,7 @@ * @since 2023-04-08 */ @Data +@JsonIgnoreProperties(ignoreUnknown = true) public class LineItem { /** * 模型名称 diff --git a/src/main/java/com/unfbx/chatgpt/entity/billing/Plan.java b/src/main/java/com/unfbx/chatgpt/entity/billing/Plan.java index 45d3ee8..e868d3a 100644 --- a/src/main/java/com/unfbx/chatgpt/entity/billing/Plan.java +++ b/src/main/java/com/unfbx/chatgpt/entity/billing/Plan.java @@ -1,5 +1,6 @@ package com.unfbx.chatgpt.entity.billing; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; /** @@ -9,6 +10,7 @@ * @since 2023-04-08 */ @Data +@JsonIgnoreProperties(ignoreUnknown = true) public class Plan { private String title; private String id; diff --git a/src/main/java/com/unfbx/chatgpt/entity/billing/Subscription.java b/src/main/java/com/unfbx/chatgpt/entity/billing/Subscription.java index 76d4bdd..4b22270 100644 --- a/src/main/java/com/unfbx/chatgpt/entity/billing/Subscription.java +++ b/src/main/java/com/unfbx/chatgpt/entity/billing/Subscription.java @@ -1,5 +1,6 @@ package com.unfbx.chatgpt.entity.billing; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @@ -10,6 +11,7 @@ * @since 2023-04-08 */ @Data +//@JsonIgnoreProperties(ignoreUnknown = true) public class Subscription { @JsonProperty("object") private String object; @@ -49,4 +51,6 @@ public class Subscription { private Object billingAddress; @JsonProperty("business_address") private Object businessAddress; + @JsonProperty("primary") + private Boolean primary; } diff --git a/src/main/java/com/unfbx/chatgpt/entity/chat/ChatChoice.java b/src/main/java/com/unfbx/chatgpt/entity/chat/ChatChoice.java index 21f6de0..68f3a43 100644 --- a/src/main/java/com/unfbx/chatgpt/entity/chat/ChatChoice.java +++ b/src/main/java/com/unfbx/chatgpt/entity/chat/ChatChoice.java @@ -1,5 +1,6 @@ package com.unfbx.chatgpt.entity.chat; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @@ -12,6 +13,7 @@ * @since 2023-03-02 */ @Data +@JsonIgnoreProperties(ignoreUnknown = true) public class ChatChoice implements Serializable { private long index; /** diff --git a/src/main/java/com/unfbx/chatgpt/entity/chat/ChatCompletion.java b/src/main/java/com/unfbx/chatgpt/entity/chat/ChatCompletion.java index fd71f41..67ebd72 100644 --- a/src/main/java/com/unfbx/chatgpt/entity/chat/ChatCompletion.java +++ b/src/main/java/com/unfbx/chatgpt/entity/chat/ChatCompletion.java @@ -13,7 +13,7 @@ import java.util.Map; /** - * 描述: chat + * 描述: chat模型参数 * * @author https:www.unfbx.com * @since 2023-03-02 @@ -34,6 +34,18 @@ public class ChatCompletion implements Serializable { */ @NonNull private List messages; + + private List 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"; + } +}