diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..c32584c
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/holiday03-GTP/src/main/java/com/sikadi/user/GTPApplication.java b/holiday03-GTP/src/main/java/com/sikadi/user/GTPApplication.java
index 9a98217..8d188b6 100644
--- a/holiday03-GTP/src/main/java/com/sikadi/user/GTPApplication.java
+++ b/holiday03-GTP/src/main/java/com/sikadi/user/GTPApplication.java
@@ -1,29 +1,13 @@
package com.sikadi.user;
-import com.bwie.common.domain.XfXhConfig;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.Bean;
-import top.hualuo.XhStreamClient;
@SpringBootApplication
public class GTPApplication {
- @Autowired
- private XfXhConfig xfXhConfig;
public static void main(String[] args) {
SpringApplication.run(GTPApplication.class, args);
}
- @Bean
- public XhStreamClient xhStreamClient (){
- return XhStreamClient.builder()
- .apiHost(xfXhConfig.getApiHost())
- .apiPath(xfXhConfig.getApiPath())
- .appId(xfXhConfig.getAppId())
- .apiKey(xfXhConfig.getApiKey())
- .apiSecret(xfXhConfig.getApiSecret())
- .build();
- }
}
diff --git a/holiday03-GTP/src/main/java/com/sikadi/user/controller/GTPController.java b/holiday03-GTP/src/main/java/com/sikadi/user/controller/GTPController.java
index 1347de8..2bc0e57 100644
--- a/holiday03-GTP/src/main/java/com/sikadi/user/controller/GTPController.java
+++ b/holiday03-GTP/src/main/java/com/sikadi/user/controller/GTPController.java
@@ -1,12 +1,15 @@
package com.sikadi.user.controller;
-import com.bwie.common.domain.StringAppGTP;
+import com.sikadi.user.listener.XfXhStreamClient;
+import com.sikadi.user.mapper.XfXhConfig;
import com.sikadi.user.service.GTPService;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
-import top.hualuo.XhStreamClient;
+
+import javax.annotation.Resource;
@RestController
public class GTPController {
@@ -16,10 +19,19 @@ public class GTPController {
- @PostMapping("/chat")
- public String chat(@RequestBody StringAppGTP stringAppGTP){
- return gtpService.chat(stringAppGTP);
- }
+ /**
+ * 发送问题
+ *
+ * @param question 问题
+ * @return 星火大模型的回答
+ */
+ @GetMapping("/sendQuestion")
+ public String sendQuestion(@RequestParam("question") String question) {
+ return gtpService.sendQuestion(question);
+ }
+
+
+
}
diff --git a/holiday03-GTP/src/main/java/com/sikadi/user/dto/MsgDTO.java b/holiday03-GTP/src/main/java/com/sikadi/user/dto/MsgDTO.java
new file mode 100644
index 0000000..3a0e6cb
--- /dev/null
+++ b/holiday03-GTP/src/main/java/com/sikadi/user/dto/MsgDTO.java
@@ -0,0 +1,50 @@
+package com.sikadi.user.dto;
+
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 消息对象
+ *
+ * @author 狐狸半面添
+ * @create 2023-09-15 0:42
+ */
+/**
+ * 消息对象
+ *
+ * @author 狐狸半面添
+ * @create 2023-09-15 0:42
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class MsgDTO {
+ /**
+ * 角色
+ */
+ private String role;
+ /**
+ * 消息内容
+ */
+ private String content;
+ /**
+ * 响应结果字段:结果序号,取值为[0,10]; 当前为保留字段,开发者可忽略
+ */
+ private Integer index;
+
+ public static final String ROLE_USER = "user";
+ public static final String ROLE_ASSISTANT = "assistant";
+
+ public static MsgDTO createUserMsg(String content) {
+ return new MsgDTO(ROLE_USER, content, null);
+ }
+
+ public static MsgDTO createAssistantMsg(String content) {
+ return new MsgDTO(ROLE_ASSISTANT, content, null);
+ }
+
+}
diff --git a/holiday03-GTP/src/main/java/com/sikadi/user/dto/request/RequestDTO.java b/holiday03-GTP/src/main/java/com/sikadi/user/dto/request/RequestDTO.java
new file mode 100644
index 0000000..7bad235
--- /dev/null
+++ b/holiday03-GTP/src/main/java/com/sikadi/user/dto/request/RequestDTO.java
@@ -0,0 +1,97 @@
+package com.sikadi.user.dto.request;
+
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.sikadi.user.dto.MsgDTO;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @description:
+ * @author: 不愧是我
+ * @date: 2023/9/28 10:12
+ * @param:
+ * @return:
+ **/
+/**
+ * 请求参数
+ * 对应生成的 JSON 结构参考 resources/demo-json/request.json
+ *
+ * @author 狐狸半面添
+ * @create 2023-09-15 0:42
+ */
+@NoArgsConstructor
+@Data
+public class RequestDTO {
+
+ @JsonProperty("header")
+ private HeaderDTO header;
+ @JsonProperty("parameter")
+ private ParameterDTO parameter;
+ @JsonProperty("payload")
+ private PayloadDTO payload;
+
+ @NoArgsConstructor
+ @Data
+ @AllArgsConstructor
+ public static class HeaderDTO {
+ /**
+ * 应用appid,从开放平台控制台创建的应用中获取
+ */
+ @JSONField(name = "app_id")
+ private String appId;
+ /**
+ * 每个用户的id,用于区分不同用户,最大长度32
+ */
+ @JSONField(name = "uid")
+ private String uid;
+ }
+
+ @NoArgsConstructor
+ @Data
+ @AllArgsConstructor
+ public static class ParameterDTO {
+ private ChatDTO chat;
+
+ @NoArgsConstructor
+ @Data
+ @AllArgsConstructor
+ public static class ChatDTO {
+ /**
+ * 指定访问的领域,general指向V1.5版本 generalv2指向V2版本。注意:不同的取值对应的url也不一样!
+ */
+ @JsonProperty("domain")
+ private String domain;
+ /**
+ * 核采样阈值。用于决定结果随机性,取值越高随机性越强即相同的问题得到的不同答案的可能性越高
+ */
+ @JsonProperty("temperature")
+ private Float temperature;
+ /**
+ * 模型回答的tokens的最大长度
+ */
+ @JSONField(name = "max_tokens")
+ private Integer maxTokens;
+ }
+ }
+
+ @NoArgsConstructor
+ @Data
+ @AllArgsConstructor
+ public static class PayloadDTO {
+ @JsonProperty("message")
+ private MessageDTO message;
+
+ @NoArgsConstructor
+ @Data
+ @AllArgsConstructor
+ public static class MessageDTO {
+ @JsonProperty("text")
+ private List text;
+ }
+ }
+}
diff --git a/holiday03-GTP/src/main/java/com/sikadi/user/mapper/XfXhConfig.java b/holiday03-GTP/src/main/java/com/sikadi/user/mapper/XfXhConfig.java
new file mode 100644
index 0000000..eac5376
--- /dev/null
+++ b/holiday03-GTP/src/main/java/com/sikadi/user/mapper/XfXhConfig.java
@@ -0,0 +1,48 @@
+package com.sikadi.user.mapper;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author 狐狸半面添
+ * @create 2023-09-15 0:46
+ */
+@Configuration
+@ConfigurationProperties(prefix = "xfxh")
+@Data
+public class XfXhConfig {
+ /**
+ * 服务引擎使用 讯飞星火认知大模型V2.0,如果使用 V1.5 需要将 hostUrl 修改为 https://spark-api.xf-yun.com/v1.1/chat
+ */
+ private String hostUrl;
+ /**
+ * 发送请求时指定的访问领域,如果是 V1.5版本 设置为 general,如果是 V2版本 设置为 generalv2
+ */
+ private String domain;
+ /**
+ * 核采样阈值。用于决定结果随机性,取值越高随机性越强即相同的问题得到的不同答案的可能性越高。取值 [0,1]
+ */
+ private Float temperature;
+ /**
+ * 模型回答的tokens的最大长度,V1.5取值为[1,4096],V2.0取值为[1,8192]。
+ */
+ private Integer maxTokens;
+ /**
+ * 大模型回复问题的最大响应时长,单位 s
+ */
+ private Integer maxResponseTime;
+ /**
+ * 用于权限验证,从服务接口认证信息中获取
+ */
+ private String appId;
+ /**
+ * 用于权限验证,从服务接口认证信息中获取
+ */
+ private String apiKey;
+ /**
+ * 用于权限验证,从服务接口认证信息中获取
+ */
+ private String apiSecret;
+
+}
diff --git a/holiday03-GTP/src/main/java/com/sikadi/user/service/GTPService.java b/holiday03-GTP/src/main/java/com/sikadi/user/service/GTPService.java
index bfb4829..6ce9f56 100644
--- a/holiday03-GTP/src/main/java/com/sikadi/user/service/GTPService.java
+++ b/holiday03-GTP/src/main/java/com/sikadi/user/service/GTPService.java
@@ -1,7 +1,6 @@
package com.sikadi.user.service;
-import com.bwie.common.domain.StringAppGTP;
-
public interface GTPService {
- String chat(StringAppGTP stringAppGTP);
+
+ String sendQuestion(String question);
}
diff --git a/holiday03-GTP/src/main/java/com/sikadi/user/service/impl/GTPServiceImpl.java b/holiday03-GTP/src/main/java/com/sikadi/user/service/impl/GTPServiceImpl.java
index 20555e4..fec9a96 100644
--- a/holiday03-GTP/src/main/java/com/sikadi/user/service/impl/GTPServiceImpl.java
+++ b/holiday03-GTP/src/main/java/com/sikadi/user/service/impl/GTPServiceImpl.java
@@ -1,27 +1,74 @@
package com.sikadi.user.service.impl;
-import com.bwie.common.domain.StringAppGTP;
-import com.bwie.common.utils.XfXhListener;
+import cn.hutool.core.util.StrUtil;
+import com.sikadi.user.dto.MsgDTO;
+import com.sikadi.user.listener.XfXhStreamClient;
+import com.sikadi.user.listener.XfXhWebSocketListener;
+import com.sikadi.user.mapper.XfXhConfig;
import com.sikadi.user.service.GTPService;
+import lombok.extern.log4j.Log4j2;
+import okhttp3.WebSocket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import top.hualuo.XhStreamClient;
-import top.hualuo.dto.MsgDTO;
-import java.util.Arrays;
+import javax.annotation.Resource;
+import java.util.Collections;
+import java.util.UUID;
+
+
@Service
+@Log4j2
public class GTPServiceImpl implements GTPService {
- @Autowired
- private XhStreamClient xhStreamClient;
+ @Resource
+ private XfXhStreamClient xfXhStreamClient;
+
+ @Resource
+ private XfXhConfig xfXhConfig;
@Override
- public String chat(StringAppGTP stringAppGTP) {
+ public String sendQuestion(String question) {
+ // 如果是无效字符串,则不对大模型进行请求
+ if (StrUtil.isBlank(question)) {
+ return "无效问题,请重新输入";
+ }
- MsgDTO dto = MsgDTO.builder().role(MsgDTO.Role.USER.getName()).content(stringAppGTP.getProblem()).build();
-
-
- return xhStreamClient.sendMsg("123", Arrays.asList(dto),new XfXhListener());;
+ // 创建消息对象
+ MsgDTO msgDTO = MsgDTO.createUserMsg(question);
+ // 创建监听器
+ XfXhWebSocketListener listener = new XfXhWebSocketListener();
+ // 发送问题给大模型,生成 websocket 连接
+ WebSocket webSocket = xfXhStreamClient.sendMsg(UUID.randomUUID().toString().substring(0, 10), Collections.singletonList(msgDTO), listener);
+ if (webSocket == null) {
+ // 归还令牌
+ xfXhStreamClient.operateToken(XfXhStreamClient.BACK_TOKEN_STATUS);
+ return "系统内部错误,请联系管理员";
+ }
+ try {
+ int count = 0;
+ // 为了避免死循环,设置循环次数来定义超时时长
+ int maxCount = xfXhConfig.getMaxResponseTime() * 5;
+ while (count <= maxCount) {
+ Thread.sleep(200);
+ if (listener.isWsCloseFlag()) {
+ break;
+ }
+ count++;
+ }
+ if (count > maxCount) {
+ return "大模型响应超时,请联系管理员";
+ }
+ // 响应大模型的答案
+ return listener.getAnswer().toString();
+ } catch (InterruptedException e) {
+ log.error("错误:" + e.getMessage());
+ return "系统内部错误,请联系管理员";
+ } finally {
+ // 关闭 websocket 连接
+ webSocket.close(1000, "");
+ // 归还令牌
+ xfXhStreamClient.operateToken(XfXhStreamClient.BACK_TOKEN_STATUS);
+ }
}
}
diff --git a/holiday03-GTP/src/main/resources/bootstrap.yml b/holiday03-GTP/src/main/resources/bootstrap.yml
index ecd2ddc..d1cf37d 100644
--- a/holiday03-GTP/src/main/resources/bootstrap.yml
+++ b/holiday03-GTP/src/main/resources/bootstrap.yml
@@ -29,8 +29,21 @@ spring:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: Sikadi
xfxh:
- apiHost: spark-api.xf-yun.com
- apiPath: /v1.1/chat
+ # 服务引擎使用 讯飞星火认知大模型V2.0,如果使用 V1.5 需要将 hostUrl 修改为 https://spark-api.xf-yun.com/v1.1/chat
+ hostUrl: https://spark-api.xf-yun.com/v2.1/chat
+ # 发送请求时指定的访问领域,如果是 V1.5版本 设置为 general,如果是 V2版本 设置为 generalv2
+ domain: generalv2
+ # 核采样阈值。用于决定结果随机性,取值越高随机性越强即相同的问题得到的不同答案的可能性越高。取值 [0,1]
+ temperature: 0.5
+ # 模型回答的tokens的最大长度,V1.5取值为[1,4096],V2.0取值为[1,8192]。
+ maxTokens: 2048
+ # 大模型回复问题的最大响应时长,单位 s
+ maxResponseTime: 30
+ # 允许同时连接大模型的 websocket 数,如果是普通(免费)用户为 2,超过这个数连接响应会报错,具体参考官网。
+ QPS: 2
+ # 用于权限验证,从服务接口认证信息中获取
appId: 9f22c545
- apiKey: N2NjMDU3ZTQwYjBkODI5ZGM3ZTVjYWY3
- apiSecret: a8e17cdcbc9addd7f21e81dff71bc177
+ # 用于权限验证,从服务接口认证信息中获取
+ apiKey: a8e17cdcbc9addd7f21e81dff71bc177
+ # 用于权限验证,从服务接口认证信息中获取
+ apiSecret: N2NjMDU3ZTQwYjBkODI5ZGM3ZTVjYWY3
diff --git a/holiday03-common/pom.xml b/holiday03-common/pom.xml
index 02e0aec..272e4ac 100644
--- a/holiday03-common/pom.xml
+++ b/holiday03-common/pom.xml
@@ -125,9 +125,37 @@
- io.github.a812086325
- xfxh-java
- 1.0
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ cn.hutool
+ hutool-all
+ 5.8.18
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ com.alibaba
+ fastjson
+ 1.2.67
+
+
+ org.java-websocket
+ Java-WebSocket
+ 1.3.8
+
+
+ com.squareup.okhttp3
+ okhttp
+ 4.10.0
+
+
+ org.projectlombok
+ lombok
diff --git a/holiday03-common/src/main/java/com/bwie/common/domain/XfXhConfig.java b/holiday03-common/src/main/java/com/bwie/common/domain/XfXhConfig.java
deleted file mode 100644
index b0e5917..0000000
--- a/holiday03-common/src/main/java/com/bwie/common/domain/XfXhConfig.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.bwie.common.domain;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-@ConfigurationProperties(prefix = "xfxh")
-@Data
-public class XfXhConfig {
-
- private StringAppGTP apiHost;
-
- private StringAppGTP apiPath;
-
- private StringAppGTP appId;
-
- private StringAppGTP apiKey;
-
- private StringAppGTP apiSecret;
-
-}
-
-
diff --git a/holiday03-common/src/main/java/com/bwie/common/utils/XfXhListener.java b/holiday03-common/src/main/java/com/bwie/common/utils/XfXhListener.java
deleted file mode 100644
index 11b7eb9..0000000
--- a/holiday03-common/src/main/java/com/bwie/common/utils/XfXhListener.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.bwie.common.utils;
-
-import com.alibaba.fastjson.JSONObject;
-import com.alibaba.nacos.shaded.org.checkerframework.checker.nullness.qual.Nullable;
-import okhttp3.Response;
-import okhttp3.WebSocket;
-import okhttp3.WebSocketListener;
-import top.hualuo.dto.MsgDTO;
-import top.hualuo.dto.ResponseDTO;
-
-import javax.validation.constraints.NotNull;
-import java.util.List;
-
-public class XfXhListener extends WebSocketListener {
- @Override
- public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) {
- super.onOpen(webSocket, response);
-
- }
-
- @Override
- public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {
- super.onMessage(webSocket, text);
- System.out.println("text:\n" + text);
- ResponseDTO responseData = JSONObject.parseObject(text, ResponseDTO.class);
- if(0 == responseData.getHeader().getCode()){
- ResponseDTO.PayloadDTO pl = responseData.getPayload();
- List tests = pl.getChoices().getText();
- MsgDTO textDTO = tests.stream().findFirst().orElse(new MsgDTO());
-
- System.out.println(textDTO.toString());
-
- if(2 == responseData.getHeader().getStatus()){
- ResponseDTO.PayloadDTO.UsageDTO.TextDTO testDto = pl.getUsage().getText();
- Integer totalTokens = testDto.getTotalTokens();
- System.out.println("本次花费:"+totalTokens + " tokens");
-
-
- webSocket.close(3,"客户端主动断开链接");
- }
-
-
- }else{
- System.out.println("返回结果错误:\n" + responseData.getHeader().getCode()+ responseData.getHeader().getMessage() );
- }
- }
-
- @Override
- public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {
- super.onFailure(webSocket, t, response);
- }
-
- @Override
- public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
- super.onClosed(webSocket, code, reason);
- }
-}