├── .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 |
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 |
--------------------------------------------------------------------------------