├── .gitignore ├── README.md ├── pom.xml └── src ├── main └── java │ └── com │ └── unfbx │ └── sparkdesk │ ├── SparkDeskClient.java │ ├── constant │ └── SparkDesk.java │ ├── entity │ ├── AIChatRequest.java │ ├── AIChatResponse.java │ ├── Chat.java │ ├── Choices.java │ ├── InHeader.java │ ├── InPayload.java │ ├── Message.java │ ├── OutHeader.java │ ├── OutPayload.java │ ├── Parameter.java │ ├── Status.java │ ├── Text.java │ └── Usage.java │ ├── listener │ └── ChatListener.java │ └── utils │ └── AuthUtils.java └── test └── java └── com └── unfbx └── AppTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | /unfbx_0xBA5D895F_public.asc 33 | /unfbx_0xBA5D895F_SECRET.gpg 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | > **原创发布转载注明出处!** 3 | 4 | > **ChatGpt Java SDK 可以看另外一个仓库:https://github.com/Grt1228/chatgpt-java** 5 | 6 | # 📖 项目简介 7 | 8 | **讯飞星火大模型的Java SDK。** 9 | 10 | 易使用、开箱即用、支持**异常**、**输出**、**会话结束**、**会话结束Token信息返回**等多种**自定义回调处理**。 11 | # 📑 更新日志 12 | - [x] 1.0.0 支持大模型chat接口,支持自定义回调处理。 13 | 14 | # 🚀 快速开始 15 | ## 1、导入pom依赖 16 | ``` 17 | 18 | com.unfbx 19 | SparkDesk-Java 20 | 1.0.0 21 | 22 | ``` 23 | ## 2、示例 24 | ```java 25 | public class AppTest { 26 | @Test 27 | public void test() { 28 | //构建客户端 29 | SparkDeskClient sparkDeskClient = SparkDeskClient.builder() 30 | .host(SparkDesk.SPARK_API_HOST_WS_V2_1) 31 | .appid("****") 32 | .apiKey("************************") 33 | .apiSecret("************************") 34 | .build(); 35 | //构建请求参数 36 | InHeader header = InHeader.builder().uid(UUID.randomUUID().toString().substring(0, 10)).appid("****").build(); 37 | Parameter parameter = Parameter.builder().chat(Chat.builder().domain("generalv2").maxTokens(2048).temperature(0.3).build()).build(); 38 | List text = new ArrayList<>(); 39 | text.add(Text.builder().role(Text.Role.USER.getName()).content("使用md文档格式写出一个三行三列的表格,表头包含:姓名,性别,爱好。数据随机即可。").build()); 40 | InPayload payload = InPayload.builder().message(Message.builder().text(text).build()).build(); 41 | AIChatRequest aiChatRequest = AIChatRequest.builder().header(header).parameter(parameter).payload(payload).build(); 42 | 43 | //发送请求 44 | sparkDeskClient.chat(new ChatListener(aiChatRequest) { 45 | //异常回调 46 | @SneakyThrows 47 | @Override 48 | public void onChatError(AIChatResponse aiChatResponse) { 49 | log.warn(String.valueOf(aiChatResponse)); 50 | } 51 | //输出回调 52 | @Override 53 | public void onChatOutput(AIChatResponse aiChatResponse) { 54 | System.out.println("content: " + aiChatResponse); 55 | } 56 | //会话结束回调 57 | @Override 58 | public void onChatEnd() { 59 | System.out.println("当前会话结束了"); 60 | } 61 | //会话结束 获取token使用信息回调 62 | @Override 63 | public void onChatToken(Usage usage) { 64 | System.out.println("token 信息:" + usage); 65 | } 66 | }); 67 | 68 | CountDownLatch countDownLatch = new CountDownLatch(1); 69 | try { 70 | countDownLatch.await(); 71 | } catch (InterruptedException e) { 72 | e.printStackTrace(); 73 | } 74 | } 75 | } 76 | 77 | ``` 78 | 79 | # ☕ 打赏 80 | 如果项目对你有帮助,可以选择打赏我。 81 | 82 | 微信截图_20230405222411 微信截图_20230405222357 83 | 84 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | com.unfbx 8 | SparkDesk-Java 9 | 1.0.0 10 | 11 | SparkDesk-Java 12 | 讯飞星火大模型Java SDK 易开发,更灵活. Xun fei SparkDesk Java SDK. SparkDesk. xfyun SDK. xinghuo.星火. 13 | https://www.unfbx.com 14 | 15 | scm:git:git://github.com/Grt1228/SparkDesk-Java.git 16 | https://github.com/Grt1228/SparkDesk-Java 17 | 18 | 19 | 20 | grt1228 21 | https://www.unfbx.com 22 | 23 | 24 | 25 | 26 | unfbx 27 | rtguo1228@qq.com 28 | unfbx 29 | https://www.unfbx.com 30 | 31 | Developer 32 | 33 | +8 34 | 35 | 36 | 37 | 38 | 39 | The MIT License 40 | https://projectlombok.org/LICENSE 41 | repo 42 | 43 | 44 | 45 | 46 | 1.8 47 | UTF-8 48 | 1.8 49 | 1.8 50 | 2.0.6 51 | 52 | 53 | 54 | 55 | com.fasterxml.jackson.core 56 | jackson-databind 57 | 2.13.3 58 | 59 | 60 | org.projectlombok 61 | lombok 62 | 1.18.24 63 | true 64 | 65 | 66 | 67 | cn.hutool 68 | hutool-all 69 | 5.8.12 70 | 71 | 72 | 73 | 74 | com.squareup.okhttp3 75 | okhttp 76 | 4.10.0 77 | 78 | 79 | 80 | 81 | com.squareup.okio 82 | okio 83 | 2.10.0 84 | 85 | 86 | org.slf4j 87 | slf4j-api 88 | ${slf4j.version} 89 | 90 | 91 | org.slf4j 92 | slf4j-simple 93 | ${slf4j.version} 94 | test 95 | 96 | 97 | junit 98 | junit 99 | 4.13.2 100 | test 101 | 102 | 103 | 104 | 105 | 106 | unfbx 107 | oss Snapshots Repository 108 | https://s01.oss.sonatype.org/content/repositories/snapshots/ 109 | 110 | 111 | unfbx 112 | oss Staging Repository 113 | https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ 114 | 115 | 116 | 117 | 118 | 119 | gen-src 120 | 121 | 122 | performRelease 123 | true 124 | 125 | 126 | 127 | 128 | 129 | maven-source-plugin 130 | 131 | 132 | attach-sources 133 | 134 | jar-no-fork 135 | 136 | 137 | 138 | 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | gen-javadoc 147 | 148 | 149 | performRelease 150 | true 151 | 152 | 153 | 154 | 155 | *.internal:*.internal.*:*.internal.*.*:*.internal.*.*.*:*.internal.*.*.*.* 156 | 157 | 158 | 159 | 160 | 161 | maven-javadoc-plugin 162 | 163 | 164 | attach-javadoc 165 | 166 | jar 167 | 168 | 169 | 170 | 171 | protected 172 | UTF-8 173 | UTF-8 174 | UTF-8 175 | 176 | ${javadoc.default.exclude.packages}:jdk.incubator.vector 177 | 178 | all,-missing 179 | 180 | https://docs.oracle.com/javase/8/docs/api 181 | 182 | 183 | -J-Duser.language=en -J-Duser.country=US 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | gen-sign 192 | 193 | 194 | performRelease 195 | true 196 | 197 | 198 | 199 | 200 | 201 | maven-gpg-plugin 202 | 203 | 204 | sign-artifacts 205 | verify 206 | 207 | sign 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | maven-clean-plugin 221 | 3.2.0 222 | 223 | 224 | maven-resources-plugin 225 | 3.3.0 226 | 227 | 228 | maven-jar-plugin 229 | 3.3.0 230 | 231 | 232 | maven-source-plugin 233 | 3.2.1 234 | 235 | 236 | maven-compiler-plugin 237 | 3.10.1 238 | 239 | 240 | maven-javadoc-plugin 241 | 3.4.1 242 | 243 | 244 | maven-surefire-plugin 245 | 3.0.0-M8 246 | 247 | 248 | maven-assembly-plugin 249 | 3.4.2 250 | 251 | 252 | maven-site-plugin 253 | 3.12.1 254 | 255 | 256 | maven-gpg-plugin 257 | 3.0.1 258 | 259 | 260 | maven-install-plugin 261 | 3.1.0 262 | 263 | 264 | maven-deploy-plugin 265 | 3.0.0 266 | 267 | 268 | maven-shade-plugin 269 | 3.4.1 270 | 271 | 272 | org.sonatype.plugins 273 | nexus-staging-maven-plugin 274 | 1.6.13 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | central 283 | aliyun maven 284 | http://maven.aliyun.com/nexus/content/groups/public/ 285 | default 286 | 287 | 288 | true 289 | 290 | 291 | 292 | false 293 | 294 | 295 | 296 | 297 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/SparkDeskClient.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk; 2 | 3 | import com.unfbx.sparkdesk.listener.ChatListener; 4 | import com.unfbx.sparkdesk.utils.AuthUtils; 5 | import lombok.Data; 6 | import lombok.SneakyThrows; 7 | import okhttp3.OkHttpClient; 8 | import okhttp3.Request; 9 | import okhttp3.WebSocket; 10 | 11 | import java.util.Objects; 12 | 13 | /** 14 | * 星火大模型客户端 15 | * 16 | * @author https://www.unfbx.com/ 17 | */ 18 | @Data 19 | public class SparkDeskClient { 20 | 21 | private String host; 22 | private String appid; 23 | private String apiKey; 24 | private String apiSecret; 25 | private OkHttpClient okHttpClient; 26 | 27 | 28 | public static Builder builder() { 29 | return new Builder(); 30 | } 31 | 32 | public static final class Builder { 33 | private String host; 34 | private String appid; 35 | private String apiKey; 36 | private String apiSecret; 37 | private OkHttpClient okHttpClient; 38 | 39 | private Builder() { 40 | } 41 | 42 | public static Builder aSparkDeskClient() { 43 | return new Builder(); 44 | } 45 | 46 | public Builder host(String host) { 47 | this.host = host; 48 | return this; 49 | } 50 | 51 | public Builder appid(String appid) { 52 | this.appid = appid; 53 | return this; 54 | } 55 | 56 | public Builder apiKey(String apiKey) { 57 | this.apiKey = apiKey; 58 | return this; 59 | } 60 | 61 | public Builder apiSecret(String apiSecret) { 62 | this.apiSecret = apiSecret; 63 | return this; 64 | } 65 | 66 | public Builder okHttpClient(OkHttpClient okHttpClient) { 67 | this.okHttpClient = okHttpClient; 68 | return this; 69 | } 70 | 71 | public SparkDeskClient build() { 72 | SparkDeskClient sparkDeskClient = new SparkDeskClient(); 73 | sparkDeskClient.host = this.host; 74 | if (Objects.isNull(this.okHttpClient)) { 75 | this.okHttpClient = new OkHttpClient.Builder().build(); 76 | } 77 | sparkDeskClient.okHttpClient = this.okHttpClient; 78 | sparkDeskClient.apiKey = this.apiKey; 79 | sparkDeskClient.appid = this.appid; 80 | sparkDeskClient.apiSecret = this.apiSecret; 81 | return sparkDeskClient; 82 | } 83 | } 84 | 85 | @SneakyThrows 86 | public WebSocket chat(T chatListener) { 87 | String authUrl = AuthUtils.getAuthUrl(host, apiKey, apiSecret); 88 | String url = authUrl.replace("http://", "ws://").replace("https://", "wss://"); 89 | Request request = new Request.Builder().url(url).build(); 90 | WebSocket webSocket = this.okHttpClient.newWebSocket(request, chatListener); 91 | return webSocket; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/constant/SparkDesk.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.constant; 2 | 3 | /** 4 | * @author https://www.unfbx.com/ 5 | * 6 | */ 7 | public class SparkDesk { 8 | 9 | /** 10 | * 星火v1.1地址:ws协议 11 | */ 12 | public final static String SPARK_API_HOST_WS_V1_1 = "http://spark-api.xf-yun.com/v1.1/chat"; 13 | /** 14 | * 星火v1.1地址:wss协议 15 | */ 16 | public final static String SPARK_API_HOST_WSS_V1_1 = "https://spark-api.xf-yun.com/v1.1/chat"; 17 | /** 18 | * 星火v2.1地址:ws协议 19 | */ 20 | public final static String SPARK_API_HOST_WS_V2_1 = "http://spark-api.xf-yun.com/v2.1/chat"; 21 | /** 22 | * 星火v2.1地址:wss协议 23 | */ 24 | public final static String SPARK_API_HOST_WSS_V2_1 = "https://spark-api.xf-yun.com/v2.1/chat"; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/AIChatRequest.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * @author https://www.unfbx.com/ 11 | */ 12 | @Data 13 | @Builder 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @JsonIgnoreProperties(ignoreUnknown = true) 17 | public class AIChatRequest { 18 | 19 | private InHeader header; 20 | private Parameter parameter; 21 | private InPayload payload; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/AIChatResponse.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * @author https://www.unfbx.com/ 11 | */ 12 | @Data 13 | @Builder 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @JsonIgnoreProperties(ignoreUnknown = true) 17 | public class AIChatResponse { 18 | 19 | private OutHeader header; 20 | private OutPayload payload; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/Chat.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * @author https://www.unfbx.com/ 12 | */ 13 | @Data 14 | @Builder 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @JsonIgnoreProperties(ignoreUnknown = true) 18 | public class Chat { 19 | /** 20 | * 取值为[general,generalv2] 21 | * 指定访问的领域,general指向V1.5版本 generalv2指向V2版本。注意:不同的取值对应的url也不一样! 22 | */ 23 | private String domain; 24 | /** 25 | * 取值为[0,1],默认为0.5 26 | */ 27 | private double temperature; 28 | /** 29 | * 取值为[1,4096],默认为2048 30 | */ 31 | @JsonProperty("max_tokens") 32 | private Integer maxTokens; 33 | /** 34 | * 取值为[1,6],默认为4 35 | * 从k个候选中随机选择⼀个(⾮等概率) 36 | */ 37 | @JsonProperty("top_k") 38 | private Integer topK; 39 | /** 40 | * 需要保障用户下的唯一性 41 | */ 42 | @JsonProperty("chat_id") 43 | private String chatId; 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/Choices.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author https://www.unfbx.com/ 13 | */ 14 | @Data 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | @JsonIgnoreProperties(ignoreUnknown = true) 19 | public class Choices { 20 | /** 21 | * 文本响应状态,取值为[0,1,2]; 0代表首个文本结果;1代表中间文本结果;2代表最后一个文本结果 22 | */ 23 | private Integer status; 24 | /** 25 | * 返回的数据序号,取值为[0,9999999] 26 | */ 27 | private Integer seq; 28 | /** 29 | * 返回信息 30 | */ 31 | private List text; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/InHeader.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * @author https://www.unfbx.com/ 12 | */ 13 | @Data 14 | @Builder 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @JsonIgnoreProperties(ignoreUnknown = true) 18 | public class InHeader { 19 | @JsonProperty("app_id") 20 | private String appid; 21 | private String uid; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/InPayload.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * @author https://www.unfbx.com/ 11 | */ 12 | @Data 13 | @Builder 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @JsonIgnoreProperties(ignoreUnknown = true) 17 | public class InPayload { 18 | private Message message; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/Message.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author https://www.unfbx.com/ 13 | */ 14 | @Data 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | @JsonIgnoreProperties(ignoreUnknown = true) 19 | public class Message { 20 | private List text; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/OutHeader.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.*; 5 | 6 | /** 7 | * @author https://www.unfbx.com/ 8 | */ 9 | @Data 10 | @Builder 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @JsonIgnoreProperties(ignoreUnknown = true) 14 | public class OutHeader { 15 | /** 16 | * 错误码,0表示正常,非0表示出错;详细释义可在接口说明文档最后的错误码说明了解 17 | * https://www.xfyun.cn/doc/spark/%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E.html 18 | */ 19 | private int code; 20 | /** 21 | * 会话状态,取值为[0,1,2];0代表首次结果;1代表中间结果;2代表最后一个结果 22 | */ 23 | private int status; 24 | /** 25 | * 会话是否成功的描述信息 26 | */ 27 | private String message; 28 | /** 29 | * 会话的唯一id,用于讯飞技术人员查询服务端会话日志使用,出现调用错误时建议留存该字段 30 | */ 31 | private String sid; 32 | 33 | /** 34 | * 错误码,0表示正常,非0表示出错;详细释义可在接口说明文档最后的错误码说明了解
35 | * https://www.xfyun.cn/doc/spark/%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E.html 36 | */ 37 | @Getter 38 | public enum Code { 39 | SUCCESS(0), 40 | ; 41 | 42 | Code(int value) { 43 | this.value = value; 44 | } 45 | 46 | private final int value; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/OutPayload.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * @author https://www.unfbx.com/ 11 | */ 12 | @Data 13 | @Builder 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @JsonIgnoreProperties(ignoreUnknown = true) 17 | public class OutPayload { 18 | /** 19 | * 问答信息 20 | */ 21 | private Choices choices; 22 | /** 23 | * Token 信息 24 | */ 25 | private Usage usage; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/Parameter.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * @author https://www.unfbx.com/ 12 | */ 13 | @Data 14 | @Builder 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @JsonIgnoreProperties(ignoreUnknown = true) 18 | public class Parameter { 19 | private Chat chat; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/Status.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * 会话状态,取值为[0,1,2];0代表首次结果;1代表中间结果;2代表最后一个结果 8 | * 9 | * @author https://www.unfbx.com/ 10 | */ 11 | @Getter 12 | public enum Status { 13 | START(0), 14 | ING(1), 15 | END(2), 16 | ; 17 | 18 | Status(int value) { 19 | this.value = value; 20 | } 21 | 22 | private final int value; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/Text.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.*; 5 | 6 | /** 7 | * @author https://www.unfbx.com/ 8 | */ 9 | @Data 10 | @Builder 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @JsonIgnoreProperties(ignoreUnknown = true) 14 | public class Text { 15 | /** 16 | * 取值为[user,assistant] 17 | */ 18 | private String role; 19 | /** 20 | * 所有content的累计tokens需控制8192以内 21 | */ 22 | private String content; 23 | /** 24 | * 结果序号,取值为[0,10]; 当前为保留字段,开发者可忽略 25 | */ 26 | private Integer index; 27 | 28 | @Getter 29 | public enum Role { 30 | 31 | USER("user"), 32 | ASSISTANT("assistant"), 33 | ; 34 | 35 | Role(String name) { 36 | this.name = name; 37 | } 38 | 39 | private final String name; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/entity/Usage.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | 7 | /** 8 | * @author https://www.unfbx.com/ 9 | */ 10 | @Data 11 | @Builder 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @JsonIgnoreProperties(ignoreUnknown = true) 15 | public class Usage { 16 | 17 | private Text text; 18 | 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | public class Text { 23 | @JsonProperty("question_tokens") 24 | private Integer questionTokens; 25 | @JsonProperty("prompt_tokens") 26 | private Integer promptTokens; 27 | @JsonProperty("completion_tokens") 28 | private Integer completionTokens; 29 | @JsonProperty("total_tokens") 30 | private Integer totalTokens; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/listener/ChatListener.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.listener; 2 | 3 | import cn.hutool.json.JSONUtil; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.unfbx.sparkdesk.entity.*; 6 | import lombok.Getter; 7 | import lombok.SneakyThrows; 8 | import lombok.extern.slf4j.Slf4j; 9 | import okhttp3.Response; 10 | import okhttp3.WebSocket; 11 | import okhttp3.WebSocketListener; 12 | import okio.ByteString; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.jetbrains.annotations.Nullable; 15 | 16 | import java.util.Objects; 17 | 18 | /** 19 | * 默认的web socket监听 20 | * 控制台打印输出信息 21 | * 22 | * @author https://www.unfbx.com/ 23 | */ 24 | @Getter 25 | @Slf4j 26 | public abstract class ChatListener extends WebSocketListener { 27 | 28 | /** 29 | * 请求大模型的参数 30 | */ 31 | private AIChatRequest aiChatRequest; 32 | 33 | /** 34 | * 构造方法,传入大模型参数 35 | * 36 | * @param aiChatRequest 大模型参数 37 | */ 38 | public ChatListener(AIChatRequest aiChatRequest) { 39 | this.aiChatRequest = aiChatRequest; 40 | } 41 | 42 | /** 43 | * WebSocket服务发生异常的回调,可以覆盖重写。 44 | * 默认抛出异常 45 | * 46 | * @param t 异常 47 | * @param response 返回值 48 | */ 49 | public void onWebSocketError(Throwable t, Response response) { 50 | log.error("调用星火模型时,WebSocket发生异常:{}", response); 51 | t.printStackTrace(); 52 | } 53 | 54 | /** 55 | * 星火大模型发生异常 56 | * 57 | * @param aiChatResponse 大模型返回值 58 | */ 59 | public abstract void onChatError(AIChatResponse aiChatResponse); 60 | 61 | /** 62 | * 星火大模型正常返回信息 63 | * 64 | * @param aiChatResponse 大模型返回值 65 | */ 66 | public abstract void onChatOutput(AIChatResponse aiChatResponse); 67 | 68 | /** 69 | * 星火大模型返回信息结束回调 70 | */ 71 | public abstract void onChatEnd(); 72 | 73 | /** 74 | * 星火大模型本次请求消耗的Token信息 75 | * 76 | * @param usage 大模型返回token信息 77 | */ 78 | public abstract void onChatToken(Usage usage); 79 | 80 | /** 81 | * 构造星火大模型请求参数,默认使用构造方法传入的信息 82 | * 可以覆盖重写 83 | * 84 | * @return 大模型请求参数 85 | */ 86 | public AIChatRequest onChatSend() { 87 | return this.aiChatRequest; 88 | } 89 | 90 | @Override 91 | public final void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) { 92 | super.onClosed(webSocket, code, reason); 93 | } 94 | 95 | @Override 96 | public final void onClosing(@NotNull WebSocket webSocket, int code, @NotNull String reason) { 97 | super.onClosing(webSocket, code, reason); 98 | } 99 | 100 | @Override 101 | public final void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) { 102 | webSocket.close(1000, ""); 103 | this.onWebSocketError(t, response); 104 | } 105 | 106 | @Override 107 | public final void onMessage(@NotNull WebSocket webSocket, @NotNull String text) { 108 | AIChatResponse aiChatResponse = JSONUtil.toBean(text, AIChatResponse.class); 109 | 110 | if (OutHeader.Code.SUCCESS.getValue() != aiChatResponse.getHeader().getCode()) { 111 | log.warn("调用星火模型发生错误,错误码为:{},请求的sid为:{}", aiChatResponse.getHeader().getCode(), aiChatResponse.getHeader().getSid()); 112 | webSocket.close(1000, "星火模型调用异常"); 113 | this.onChatError(aiChatResponse); 114 | return; 115 | } 116 | 117 | this.onChatOutput(aiChatResponse); 118 | 119 | if (Status.END.getValue() == aiChatResponse.getHeader().getStatus()) { 120 | // 可以关闭连接,释放资源 121 | webSocket.close(1000, "星火模型返回结束"); 122 | Usage usage = aiChatResponse.getPayload().getUsage(); 123 | this.onChatEnd(); 124 | this.onChatToken(usage); 125 | } 126 | } 127 | 128 | @Override 129 | public final void onMessage(@NotNull WebSocket webSocket, @NotNull ByteString bytes) { 130 | super.onMessage(webSocket, bytes); 131 | } 132 | 133 | @SneakyThrows 134 | @Override 135 | public final void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) { 136 | super.onOpen(webSocket, response); 137 | AIChatRequest aiChatRequest = this.onChatSend(); 138 | ObjectMapper mapper = new ObjectMapper(); 139 | webSocket.send(mapper.writeValueAsString(Objects.isNull(aiChatRequest) ? this.getAiChatRequest() : aiChatRequest)); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/com/unfbx/sparkdesk/utils/AuthUtils.java: -------------------------------------------------------------------------------- 1 | package com.unfbx.sparkdesk.utils; 2 | 3 | import okhttp3.HttpUrl; 4 | 5 | import javax.crypto.Mac; 6 | import javax.crypto.spec.SecretKeySpec; 7 | import java.net.MalformedURLException; 8 | import java.net.URL; 9 | import java.nio.charset.StandardCharsets; 10 | import java.security.InvalidKeyException; 11 | import java.security.NoSuchAlgorithmException; 12 | import java.time.ZoneId; 13 | import java.time.ZonedDateTime; 14 | import java.time.format.DateTimeFormatter; 15 | import java.util.*; 16 | 17 | /** 18 | * 鉴权工具 19 | * 20 | * @author https://www.unfbx.com/ 21 | */ 22 | public class AuthUtils { 23 | 24 | /** 25 | * 日期格式化 26 | */ 27 | public final static DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); 28 | public final static String preStr = "host: %s\n" + 29 | "date: %s\n" + 30 | "GET %s HTTP/1.1"; 31 | 32 | 33 | /** 34 | * 鉴权方法 35 | * 36 | * @param hostUrl 地址 37 | * @param apiKey apikey 38 | * @param apiSecret apiSecret 39 | * @return 鉴权信息 40 | * @throws MalformedURLException e 41 | * @throws InvalidKeyException e 42 | * @throws NoSuchAlgorithmException e 43 | */ 44 | public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws MalformedURLException, InvalidKeyException, NoSuchAlgorithmException { 45 | URL url = new URL(hostUrl); 46 | ZonedDateTime now = ZonedDateTime.now(ZoneId.of("GMT")); 47 | String date = now.format(dateTimeFormatter); 48 | // SHA256加密 49 | Mac mac = Mac.getInstance("hmacsha256"); 50 | SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256"); 51 | mac.init(spec); 52 | byte[] hexDigits = mac.doFinal(String.format(preStr, url.getHost(), date, url.getPath()).getBytes(StandardCharsets.UTF_8)); 53 | // Base64加密 54 | String sha = Base64.getEncoder().encodeToString(hexDigits); 55 | // 拼接 56 | String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha); 57 | // 拼接地址 58 | HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder(). 59 | addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))). 60 | addQueryParameter("date", date). 61 | addQueryParameter("host", url.getHost()). 62 | build(); 63 | return httpUrl.toString(); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/com/unfbx/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.unfbx; 2 | 3 | import com.unfbx.sparkdesk.SparkDeskClient; 4 | import com.unfbx.sparkdesk.constant.SparkDesk; 5 | import com.unfbx.sparkdesk.entity.*; 6 | import com.unfbx.sparkdesk.listener.ChatListener; 7 | import lombok.SneakyThrows; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.junit.Test; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.UUID; 14 | import java.util.concurrent.CountDownLatch; 15 | 16 | /** 17 | * Hello world! 18 | */ 19 | @Slf4j 20 | public class AppTest { 21 | 22 | @Test 23 | public void test() { 24 | SparkDeskClient sparkDeskClient = SparkDeskClient.builder() 25 | .host(SparkDesk.SPARK_API_HOST_WS_V2_1) 26 | .appid("****") 27 | .apiKey("************************") 28 | .apiSecret("************************") 29 | .build(); 30 | InHeader header = InHeader.builder().uid(UUID.randomUUID().toString().substring(0, 10)).appid("****").build(); 31 | Parameter parameter = Parameter.builder().chat(Chat.builder().domain("generalv2").maxTokens(2048).temperature(0.3).build()).build(); 32 | List text = new ArrayList<>(); 33 | text.add(Text.builder().role(Text.Role.USER.getName()).content("使用md文档格式写出一个三行三列的表格,表头包含:姓名,性别,爱好。数据随机即可。").build()); 34 | InPayload payload = InPayload.builder().message(Message.builder().text(text).build()).build(); 35 | AIChatRequest aiChatRequest = AIChatRequest.builder().header(header).parameter(parameter).payload(payload).build(); 36 | 37 | sparkDeskClient.chat(new ChatListener(aiChatRequest) { 38 | @SneakyThrows 39 | @Override 40 | public void onChatError(AIChatResponse aiChatResponse) { 41 | log.warn(String.valueOf(aiChatResponse)); 42 | } 43 | 44 | @Override 45 | public void onChatOutput(AIChatResponse aiChatResponse) { 46 | System.out.println("content: " + aiChatResponse); 47 | } 48 | 49 | @Override 50 | public void onChatEnd() { 51 | System.out.println("当前会话结束了"); 52 | } 53 | 54 | @Override 55 | public void onChatToken(Usage usage) { 56 | System.out.println("token 信息:" + usage); 57 | } 58 | }); 59 | 60 | CountDownLatch countDownLatch = new CountDownLatch(1); 61 | try { 62 | countDownLatch.await(); 63 | } catch (InterruptedException e) { 64 | e.printStackTrace(); 65 | } 66 | } 67 | } 68 | --------------------------------------------------------------------------------