diff --git a/README.md b/README.md
index 6c8ae3f..3150c3f 100644
--- a/README.md
+++ b/README.md
@@ -79,6 +79,7 @@ WebSocket参考:[OpenAIWebSocketEventSourceListener](https://github.com/Grt122
- 支持全部OpenAI的Api
# 📑 更新日志
+- [x] 1.1.6 ChatCompletion接口支持logprobs参数设置,Assistant相关接口支持流式输出
- [x] 1.1.5 Bug Fix
- [x] 1.1.3 支持Assistant、Run、Thread、Message Api。测试案例[OpenAiClientTest](https://github.com/Grt1228/chatgpt-java/blob/develop/src/test/java/com/unfbx/chatgpt/v1_1_3/OpenAiClientTest.java)
- [x] 1.1.2-beta0 支持附加图片的ChatCompletion、指定返回数据格式、Tool Call、Dall-e-3生成图片、FineTuneJob、文本转语音TTS。官方文档示例:[chatgpt-java.unfbx.com](https://chatgpt-java.unfbx.com/docs/category/-%E6%A0%B8%E5%BF%83%E5%8A%9F%E8%83%BD) 。测试案例[OpenAiClientTest](https://github.com/Grt1228/chatgpt-java/blob/develop/src/test/java/com/unfbx/chatgpt/v1_1_2/OpenAiClientTest.java)
diff --git a/README_EN.md b/README_EN.md
index 2ad842f..af87ee2 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -65,6 +65,7 @@ WebSocket Reference:[OpenAIWebSocketEventSourceListener](https://github.com/Gr
- Supports all OpenAI APIs.
# 📑 Update Log
+- [x] 1.1.6 ChatCompletion api support logprobs param. Assistant about api support sse stream output.
- [x] 1.1.5 Bug Fix
- [x] 1.1.3 Upgrade to support Assistant、Run、Thread、Message Api. eg: [OpenAiClientTest](https://github.com/Grt1228/chatgpt-java/blob/develop/src/test/java/com/unfbx/chatgpt/v1_1_3/OpenAiClientTest.java)
- [x] 1.1.2-beta0 Upgrade to support chat completion with picture GPT-4V、return JSON model、Tool Call、Dall-e-3、Fine Tune Job、TTS.
diff --git a/pom.xml b/pom.xml
index b8aa41e..ae6f307 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.unfbx
chatgpt-java
- 1.1.5
+ 1.1.6
chatgpt-java
OpenAI Java SDK, OpenAI Api for Java. ChatGPT Java SDK .
https://chatgpt-java.unfbx.com
diff --git a/src/main/java/com/unfbx/chatgpt/OpenAiClient.java b/src/main/java/com/unfbx/chatgpt/OpenAiClient.java
index 97d3778..4425766 100644
--- a/src/main/java/com/unfbx/chatgpt/OpenAiClient.java
+++ b/src/main/java/com/unfbx/chatgpt/OpenAiClient.java
@@ -57,10 +57,12 @@
import com.unfbx.chatgpt.interceptor.DefaultOpenAiAuthInterceptor;
import com.unfbx.chatgpt.plugin.PluginAbstract;
import com.unfbx.chatgpt.plugin.PluginParam;
+import com.unfbx.chatgpt.utils.SSEUtil;
import io.reactivex.Single;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
+import okhttp3.sse.EventSourceListener;
import org.jetbrains.annotations.NotNull;
import retrofit2.Call;
import retrofit2.Callback;
@@ -125,6 +127,9 @@ public class OpenAiClient {
@Getter
private PageRequest pageRequest = PageRequest.builder().build();
+ @Getter
+ private static final Headers assistantsHeader = Headers.of("OpenAI-Beta", "assistants=v1");
+
/**
* 构造器
*
@@ -1283,6 +1288,27 @@ public RunResponse run(String threadId, Run run) {
return this.openAiApi.run(threadId, run).blockingGet();
}
+ /**
+ * SSE创建Run
+ *
+ * @param threadId 线程id
+ * @param run run
+ * @param eventSourceListener eventSourceListener
+ * @return
+ * @since 1.1.6
+ */
+ public void runWithStream(String threadId, Run run, EventSourceListener eventSourceListener) {
+ if (!run.isStream()) {
+ run.setStream(true);
+ }
+ SSEUtil.post(this.okHttpClient,
+ this.apiHost + "v1/threads/" + threadId + "/runs",
+ assistantsHeader,
+ run,
+ eventSourceListener
+ );
+ }
+
/**
* 检索run详细信息
diff --git a/src/main/java/com/unfbx/chatgpt/entity/assistant/Assistant.java b/src/main/java/com/unfbx/chatgpt/entity/assistant/Assistant.java
index 9aca6bb..596ee3c 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/assistant/Assistant.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/assistant/Assistant.java
@@ -18,7 +18,7 @@
public class Assistant implements Serializable {
/**
- * All models except gpt-3.5-turbo-0301 supported. retrieval tool requires gpt-4-1106-preview or gpt-3.5-turbo-1106.
+ * All models except gpt-3.5-turbo-0301 supported. retrieval tool requires gpt-4-1106-preview or gpt-3.5-turbo-1106.
*
* @see com.unfbx.chatgpt.entity.chat.ChatCompletion.Model
*/
@@ -36,18 +36,32 @@ public class Assistant implements Serializable {
*/
private String instructions;
/**
- * 助手上启用的工具列表。每个助手最多可以有 128 个工具。工具可以是 code_interpreter、retrieval或function。
+ * 助手上启用的工具列表。每个助手最多可以有 128 个工具。工具可以是 code_interpreter、file_search、retrieval或function。
*/
private List tools;
/**
- * 附加到该助手的文件 ID 列表。助手最多可以附加 20 个文件。文件按其创建日期升序排列。
+ * tool_resources
*/
- @JsonProperty("file_ids")
- private List fileIds;
+ @JsonProperty("tool_resources")
+ private ToolResources toolResources;
/**
* Set of 16 key-value pairs that can be attached to an object.
* This can be useful for storing additional information about the object in a structured format.
* Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.
*/
private Map metadata;
+
+ private Double temperature;
+
+ @JsonProperty("top_p")
+ private Double topP;
+
+ /**
+ * `auto` is the default value
+ */
+ @JsonProperty("response_format")
+ private Object responseFormat;
+
+
+
}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/assistant/AssistantResponse.java b/src/main/java/com/unfbx/chatgpt/entity/assistant/AssistantResponse.java
index 8254c6e..bf6cedb 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/assistant/AssistantResponse.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/assistant/AssistantResponse.java
@@ -43,11 +43,14 @@ public class AssistantResponse implements Serializable {
* 助手上启用的工具列表。每个助手最多可以有 128 个工具。工具可以是 code_interpreter、retrieval或function。
*/
private List tools;
- /**
- * 附加到该助手的文件 ID 列表。助手最多可以附加 20 个文件。文件按其创建日期升序排列。
- */
- @JsonProperty("file_ids")
- private List fileIds;
+
+ @JsonProperty("tool_resources")
+ private ToolResources toolResources;
+
+ @JsonProperty("top_p")
+ private Double topP;
+
+ private Double temperature;
/**
* Set of 16 key-value pairs that can be attached to an object.
* This can be useful for storing additional information about the object in a structured format.
@@ -60,5 +63,8 @@ public class AssistantResponse implements Serializable {
@JsonProperty("created_at")
private Long createdAt;
+ @JsonProperty("response_format")
+ private Object responseFormat;
+
}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/assistant/CodeInterpreter.java b/src/main/java/com/unfbx/chatgpt/entity/assistant/CodeInterpreter.java
new file mode 100644
index 0000000..a1a239b
--- /dev/null
+++ b/src/main/java/com/unfbx/chatgpt/entity/assistant/CodeInterpreter.java
@@ -0,0 +1,21 @@
+package com.unfbx.chatgpt.entity.assistant;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 描述:
+ *
+ * @author https://www.unfbx.com
+ * @since 2024-05-07
+ */
+@Data
+@Builder
+public class CodeInterpreter {
+
+ @JsonProperty("file_ids")
+ private List fileIds;
+}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/assistant/FileSearch.java b/src/main/java/com/unfbx/chatgpt/entity/assistant/FileSearch.java
new file mode 100644
index 0000000..7de86ed
--- /dev/null
+++ b/src/main/java/com/unfbx/chatgpt/entity/assistant/FileSearch.java
@@ -0,0 +1,24 @@
+package com.unfbx.chatgpt.entity.assistant;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 描述:
+ *
+ * @author https://www.unfbx.com
+ * @since 2024-05-07
+ */
+@Data
+@Builder
+public class FileSearch {
+
+ @JsonProperty("vector_store_ids")
+ private List vectorStoreIds;
+
+ @JsonProperty("vector_stores")
+ private List vectorStores;
+}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/assistant/Tool.java b/src/main/java/com/unfbx/chatgpt/entity/assistant/Tool.java
index fde61f3..79401f9 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/assistant/Tool.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/assistant/Tool.java
@@ -26,14 +26,16 @@ public class Tool implements Serializable {
/**
- * 支持的三种类型
+ * 支持的种类型
*/
@Getter
@AllArgsConstructor
public enum Type {
CODE_INTERPRETER("code_interpreter"),
+ @Deprecated
RETRIEVAL("retrieval"),
FUNCTION("function"),
+ FILE_SEARCH("file_search"),
;
private final String name;
}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/assistant/ToolResources.java b/src/main/java/com/unfbx/chatgpt/entity/assistant/ToolResources.java
new file mode 100644
index 0000000..5cfc564
--- /dev/null
+++ b/src/main/java/com/unfbx/chatgpt/entity/assistant/ToolResources.java
@@ -0,0 +1,21 @@
+package com.unfbx.chatgpt.entity.assistant;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * 描述:
+ *
+ * @author https://www.unfbx.com
+ * @since 2024-05-07
+ */
+@Data
+@Builder
+public class ToolResources {
+
+ @JsonProperty("code_interpreter")
+ private CodeInterpreter codeInterpreter;
+ @JsonProperty("code_interpreter")
+ private FileSearch fileSearch;
+}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/assistant/VectorStore.java b/src/main/java/com/unfbx/chatgpt/entity/assistant/VectorStore.java
new file mode 100644
index 0000000..0818573
--- /dev/null
+++ b/src/main/java/com/unfbx/chatgpt/entity/assistant/VectorStore.java
@@ -0,0 +1,25 @@
+package com.unfbx.chatgpt.entity.assistant;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 描述:
+ *
+ * @author https://www.unfbx.com
+ * @since 2024-05-07
+ */
+@Data
+@Builder
+public class VectorStore {
+
+ @JsonProperty("file_ids")
+ private List fileIds;
+
+ @JsonProperty("metadata")
+ private Map metadata;
+}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/assistant/run/Run.java b/src/main/java/com/unfbx/chatgpt/entity/assistant/run/Run.java
index 7661dde..67289cc 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/assistant/run/Run.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/assistant/run/Run.java
@@ -48,4 +48,6 @@ public class Run implements Serializable {
* Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.
*/
private Map metadata;
+
+ private boolean stream;
}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/chat/BaseChatCompletion.java b/src/main/java/com/unfbx/chatgpt/entity/chat/BaseChatCompletion.java
index 9e10138..071c168 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/chat/BaseChatCompletion.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/chat/BaseChatCompletion.java
@@ -145,6 +145,15 @@ public class BaseChatCompletion implements Serializable {
* @since 1.1.2
*/
private Integer seed;
+ /**
+ * @since 1.1.6
+ */
+ private Boolean logprobs;
+ /**
+ * @since 1.1.6
+ */
+ @JsonProperty("top_logprobs")
+ private Integer topLogprobs;
/**
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 6b1fb1e..649dd51 100644
--- a/src/main/java/com/unfbx/chatgpt/entity/chat/ChatChoice.java
+++ b/src/main/java/com/unfbx/chatgpt/entity/chat/ChatChoice.java
@@ -29,4 +29,6 @@ public class ChatChoice implements Serializable {
private Message message;
@JsonProperty("finish_reason")
private String finishReason;
+
+ private LogprobContent logprobs;
}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/chat/Logprob.java b/src/main/java/com/unfbx/chatgpt/entity/chat/Logprob.java
new file mode 100644
index 0000000..79b16aa
--- /dev/null
+++ b/src/main/java/com/unfbx/chatgpt/entity/chat/Logprob.java
@@ -0,0 +1,28 @@
+package com.unfbx.chatgpt.entity.chat;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 描述:
+ *
+ * @author https:www.unfbx.com
+ * @since 2023-12-25
+ */
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class Logprob implements Serializable {
+ private String token;
+
+ private BigDecimal logprob;
+
+ private List bytes;
+
+ @JsonProperty("top_logprobs")
+ private List topLogprobs;
+}
diff --git a/src/main/java/com/unfbx/chatgpt/entity/chat/LogprobContent.java b/src/main/java/com/unfbx/chatgpt/entity/chat/LogprobContent.java
new file mode 100644
index 0000000..3f852ea
--- /dev/null
+++ b/src/main/java/com/unfbx/chatgpt/entity/chat/LogprobContent.java
@@ -0,0 +1,20 @@
+package com.unfbx.chatgpt.entity.chat;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 描述:
+ *
+ * @author https:www.unfbx.com
+ * @since 2023-12-25
+ */
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class LogprobContent implements Serializable {
+
+ private List content;
+}
diff --git a/src/main/java/com/unfbx/chatgpt/utils/SSEUtil.java b/src/main/java/com/unfbx/chatgpt/utils/SSEUtil.java
new file mode 100644
index 0000000..2144769
--- /dev/null
+++ b/src/main/java/com/unfbx/chatgpt/utils/SSEUtil.java
@@ -0,0 +1,129 @@
+package com.unfbx.chatgpt.utils;
+
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.http.ContentType;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.unfbx.chatgpt.exception.BaseException;
+import com.unfbx.chatgpt.exception.CommonError;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+import okhttp3.sse.EventSource;
+import okhttp3.sse.EventSourceListener;
+import okhttp3.sse.EventSources;
+
+import java.util.Objects;
+
+/**
+ * 描述:
+ *
+ * @author https://www.unfbx.com
+ * @since 2024-05-07
+ */
+@Slf4j
+public class SSEUtil {
+
+ /**
+ * 执行get sse请求
+ *
+ * @param okHttpClient
+ * @param url
+ * @param eventSourceListener
+ * @param
+ */
+ public static void get(OkHttpClient okHttpClient, String url, EventSourceListener eventSourceListener) {
+ get(okHttpClient, url, Headers.of(MapUtil.empty()), eventSourceListener);
+ }
+
+ /**
+ * 执行get sse请求
+ *
+ * @param okHttpClient
+ * @param url
+ * @param headers
+ * @param eventSourceListener
+ */
+ public static void get(OkHttpClient okHttpClient, String url, Headers headers, EventSourceListener eventSourceListener) {
+ Request request = new Request.Builder()
+ .url(url)
+ .get()
+ .headers(headers)
+ .build();
+ get(okHttpClient, request, eventSourceListener);
+ }
+
+ /**
+ * 执行get sse请求
+ *
+ * @param okHttpClient
+ * @param request
+ * @param eventSourceListener
+ * @param
+ */
+ public static void get(OkHttpClient okHttpClient, Request request, EventSourceListener eventSourceListener) {
+ execute(okHttpClient, request, eventSourceListener);
+ }
+
+
+ /**
+ * 执行post sse请求
+ *
+ * @param okHttpClient
+ * @param url
+ * @param headers
+ * @param body
+ * @param eventSourceListener
+ * @param
+ */
+ public static void post(OkHttpClient okHttpClient, String url, Headers headers, T body, EventSourceListener eventSourceListener) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ String requestBody = mapper.writeValueAsString(body);
+ Request request = new Request.Builder()
+ .url(url)
+ .headers(headers)
+ .post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), requestBody))
+ .build();
+ execute(okHttpClient, request, eventSourceListener);
+ } catch (JsonProcessingException e) {
+ log.error("请求参数解析异常:{}", e);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 执行post sse请求
+ *
+ * @param okHttpClient
+ * @param url
+ * @param body
+ * @param eventSourceListener
+ * @param
+ */
+ public static void post(OkHttpClient okHttpClient, String url, T body, EventSourceListener eventSourceListener) {
+ post(okHttpClient, url, Headers.of(MapUtil.empty()), body, eventSourceListener);
+ }
+
+ /**
+ * 执行sse请求
+ *
+ * @param okHttpClient
+ * @param request
+ * @param eventSourceListener
+ * @param
+ */
+ public static void execute(OkHttpClient okHttpClient, Request request, EventSourceListener eventSourceListener) {
+ if (Objects.isNull(eventSourceListener)) {
+ log.error("参数异常:EventSourceListener不能为空,可以参考:com.unfbx.chatgpt.sse.ConsoleEventSourceListener");
+ throw new BaseException(CommonError.PARAM_ERROR);
+ }
+ try {
+ EventSource.Factory factory = EventSources.createFactory(okHttpClient);
+ //创建事件
+ factory.newEventSource(request, eventSourceListener);
+ } catch (Exception e) {
+ log.error("请求参数解析异常:{}", e);
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/test/java/com/unfbx/chatgpt/v1_1_6/AssistantTest.java b/src/test/java/com/unfbx/chatgpt/v1_1_6/AssistantTest.java
new file mode 100644
index 0000000..9b63b80
--- /dev/null
+++ b/src/test/java/com/unfbx/chatgpt/v1_1_6/AssistantTest.java
@@ -0,0 +1,110 @@
+package com.unfbx.chatgpt.v1_1_6;
+
+import com.unfbx.chatgpt.FirstKeyStrategy;
+import com.unfbx.chatgpt.OpenAiClient;
+import com.unfbx.chatgpt.OpenAiStreamClient;
+import com.unfbx.chatgpt.entity.assistant.Tool;
+import com.unfbx.chatgpt.entity.assistant.run.Run;
+import com.unfbx.chatgpt.entity.assistant.run.RunResponse;
+import com.unfbx.chatgpt.entity.chat.BaseChatCompletion;
+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.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.OkHttpClient;
+import okhttp3.ResponseBody;
+import okhttp3.internal.sse.RealEventSource;
+import okhttp3.logging.HttpLoggingInterceptor;
+import okio.Buffer;
+import okio.BufferedSource;
+import org.junit.Before;
+import org.junit.Test;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+import java.io.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 描述:
+ *
+ * @author https://www.unfbx.com
+ * @since 2024-05-06
+ */
+@Slf4j
+public class AssistantTest {
+
+ private OpenAiClient client;
+ private OpenAiStreamClient streamClient;
+
+ @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();
+ client = OpenAiClient.builder()
+ .apiKey(Arrays.asList("sk-****"))
+ .keyStrategy(new FirstKeyStrategy())
+ .okHttpClient(okHttpClient)
+ .apiHost("https://dgr.life/")
+ .build();
+
+ streamClient = OpenAiStreamClient.builder()
+ //支持多key传入,请求时候随机选择
+ .apiKey(Arrays.asList("sk-***"))
+ //自定义key的获取策略:默认KeyRandomStrategy
+ .keyStrategy(new KeyRandomStrategy())
+ .authInterceptor(new DynamicKeyOpenAiAuthInterceptor())
+ .okHttpClient(okHttpClient)
+ .apiHost("https://dgr.life/")
+ .build();
+ }
+
+
+ /**
+ * 创建run
+ */
+ @Test
+ public void run() {
+ HashMap map = new HashMap<>();
+ map.put("A", "a");
+ Tool tool = Tool.builder().type(Tool.Type.CODE_INTERPRETER.getName()).build();
+ Run run = Run
+ .builder()
+ .assistantId("asst_jxUD2Byvy4mdI3fR354y5Rwd")
+ .model(BaseChatCompletion.Model.GPT_3_5_TURBO_1106.getName())
+ .instructions("你是一个数学导师。当我问你问题时,编写并运行Java代码来回答问题。")
+ .tools(Collections.singletonList(tool))
+ .stream(true)
+ .metadata(map).build();
+ ConsoleEventSourceListener eventSourceListener = new ConsoleEventSourceListener();
+ client.runWithStream("thread_ZOGnTQpCkxGJgqplvWTOIJs7", run, eventSourceListener);
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ try {
+ countDownLatch.await();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/test/java/com/unfbx/chatgpt/v1_1_6/OpenAiClientTest.java b/src/test/java/com/unfbx/chatgpt/v1_1_6/OpenAiClientTest.java
new file mode 100644
index 0000000..b1a70df
--- /dev/null
+++ b/src/test/java/com/unfbx/chatgpt/v1_1_6/OpenAiClientTest.java
@@ -0,0 +1,141 @@
+package com.unfbx.chatgpt.v1_1_6;
+
+
+import com.unfbx.chatgpt.FirstKeyStrategy;
+import com.unfbx.chatgpt.OpenAiClient;
+import com.unfbx.chatgpt.OpenAiStreamClient;
+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.extern.slf4j.Slf4j;
+import okhttp3.OkHttpClient;
+import okhttp3.logging.HttpLoggingInterceptor;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 描述: 测试类
+ *
+ * @author https:www.unfbx.com
+ * 2023-12-25
+ */
+@Slf4j
+public class OpenAiClientTest {
+
+ private OpenAiClient client;
+ private OpenAiStreamClient streamClient;
+
+
+ @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();
+ client = OpenAiClient.builder()
+ //支持多key传入,请求时候随机选择
+ .apiKey(Arrays.asList("sk-*************************************"))
+ //自定义key的获取策略:默认KeyRandomStrategy
+ //.keyStrategy(new KeyRandomStrategy())
+ .keyStrategy(new FirstKeyStrategy())
+ .okHttpClient(okHttpClient)
+ //自己做了代理就传代理地址,没有可不不传,(关注公众号回复:openai ,获取免费的测试代理地址)
+ .apiHost("https://*************/")
+ .build();
+
+ streamClient = OpenAiStreamClient.builder()
+ //支持多key传入,请求时候随机选择
+ .apiKey(Arrays.asList("sk-*************************************"))
+ //自定义key的获取策略:默认KeyRandomStrategy
+ .keyStrategy(new KeyRandomStrategy())
+ .authInterceptor(new DynamicKeyOpenAiAuthInterceptor())
+ .okHttpClient(okHttpClient)
+ //自己做了代理就传代理地址,没有可不不传,(关注公众号回复:openai ,获取免费的测试代理地址)
+ .apiHost("https://*********/")
+ .build();
+ }
+
+ /**
+ * 聊天模型支持图片流式示例
+ */
+ @Test
+ public void pictureChat() {
+ Content textContent = Content.builder().text("What’s in this image?").type(Content.Type.TEXT.getName()).build();
+ ImageUrl imageUrl = ImageUrl.builder().url("https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg").build();
+ Content imageContent = Content.builder().imageUrl(imageUrl).type(Content.Type.IMAGE_URL.getName()).build();
+ List contentList = new ArrayList<>();
+ contentList.add(textContent);
+ contentList.add(imageContent);
+ MessagePicture message = MessagePicture.builder().role(Message.Role.USER).content(contentList).build();
+ ChatCompletionWithPicture chatCompletion = ChatCompletionWithPicture
+ .builder()
+ .messages(Collections.singletonList(message))
+ .model(ChatCompletion.Model.GPT_4_VISION_PREVIEW.getName())
+ .build();
+ ChatCompletionResponse chatCompletionResponse = client.chatCompletion(chatCompletion);
+ chatCompletionResponse.getChoices().forEach(e -> System.out.println(e.getMessage()));
+ }
+
+
+ @Test
+ public void chat() {
+ //聊天模型:gpt-3.5
+ Message message = Message.builder().role(Message.Role.USER).content("你好啊我的伙伴!").build();
+ ChatCompletion chatCompletion = ChatCompletion
+ .builder()
+ .messages(Collections.singletonList(message))
+ .model(ChatCompletion.Model.GPT_3_5_TURBO.getName())
+ .logprobs(true)
+ .topLogprobs(2)
+ .build();
+ ChatCompletionResponse chatCompletionResponse = client.chatCompletion(chatCompletion);
+ chatCompletionResponse.getChoices().forEach(e -> {
+ System.out.println(e.getMessage());
+ });
+ }
+
+
+ @Test
+ public void chatCompletions() {
+ ConsoleEventSourceListener eventSourceListener = new ConsoleEventSourceListener();
+ Message message = Message.builder().role(Message.Role.USER).content("random one word!").build();
+ ChatCompletion chatCompletion = ChatCompletion
+ .builder()
+ .model(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName())
+ .temperature(0.2)
+ .maxTokens(2048)
+ .messages(Collections.singletonList(message))
+ .stream(true)
+ .logprobs(true)
+ .topLogprobs(2)
+ .build();
+ streamClient.streamChatCompletion(chatCompletion, eventSourceListener);
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ try {
+ countDownLatch.await();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+}