From cba49a30ad28f3e550d68329db7fb8f85bad9d23 Mon Sep 17 00:00:00 2001 From: fst1996 <2411194573@qq.com> Date: Thu, 5 Oct 2023 00:01:50 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=AF=E9=A3=9E=E6=98=9F=E7=81=AB=E5=A4=A7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 19 ++- src/main/java/com/bwie/WorkApplication.java | 12 ++ src/main/java/com/bwie/common/MsgDTO.java | 38 +++++ .../common/{ => request}/LoginRequest.java | 2 +- .../com/bwie/common/request/RequestDTO.java | 93 +++++++++++ .../com/bwie/common/response/ResponseDTO.java | 112 +++++++++++++ .../com/bwie/component/XfXhStreamClient.java | 153 ++++++++++++++++++ src/main/java/com/bwie/config/CorsConfig.java | 24 +++ src/main/java/com/bwie/config/XfXhConfig.java | 54 +++++++ .../com/bwie/controller/ChatController.java | 98 +++++++++++ .../com/bwie/controller/UserController.java | 2 +- .../bwie/listener/XfXhWebSocketListener.java | 72 +++++++++ src/main/java/com/bwie/mapper/UserMapper.java | 2 +- .../java/com/bwie/service/UserService.java | 2 +- .../bwie/service/impl/UserServiceImpl.java | 2 +- src/main/resources/application.yml | 8 +- src/main/resources/mapper/UserMapper.xml | 2 +- target/classes/com/bwie/test/Test01.class | Bin 652 -> 0 bytes target/maven-archiver/pom.properties | 5 - .../compile/default-compile/createdFiles.lst | 5 +- .../compile/default-compile/inputFiles.lst | 16 ++ .../default-testCompile/inputFiles.lst | 0 target/test-10.01-1.0-SNAPSHOT.jar | Bin 2703 -> 0 bytes 23 files changed, 704 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/bwie/WorkApplication.java create mode 100644 src/main/java/com/bwie/common/MsgDTO.java rename src/main/java/com/bwie/common/{ => request}/LoginRequest.java (77%) create mode 100644 src/main/java/com/bwie/common/request/RequestDTO.java create mode 100644 src/main/java/com/bwie/common/response/ResponseDTO.java create mode 100644 src/main/java/com/bwie/component/XfXhStreamClient.java create mode 100644 src/main/java/com/bwie/config/CorsConfig.java create mode 100644 src/main/java/com/bwie/config/XfXhConfig.java create mode 100644 src/main/java/com/bwie/controller/ChatController.java create mode 100644 src/main/java/com/bwie/listener/XfXhWebSocketListener.java delete mode 100644 target/classes/com/bwie/test/Test01.class delete mode 100644 target/maven-archiver/pom.properties delete mode 100644 target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst delete mode 100644 target/test-10.01-1.0-SNAPSHOT.jar diff --git a/pom.xml b/pom.xml index 7777b04..806d94d 100644 --- a/pom.xml +++ b/pom.xml @@ -7,6 +7,19 @@ com.bwie test-10.01 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + org.junit.jupiter @@ -40,11 +53,13 @@ Java-WebSocket 1.3.8 + com.squareup.okhttp3 okhttp - 4.10.0 + 4.9.3 + org.projectlombok lombok @@ -91,6 +106,8 @@ aws-java-sdk-core 1.12.68 + + diff --git a/src/main/java/com/bwie/WorkApplication.java b/src/main/java/com/bwie/WorkApplication.java new file mode 100644 index 0000000..8e80ef3 --- /dev/null +++ b/src/main/java/com/bwie/WorkApplication.java @@ -0,0 +1,12 @@ +package com.bwie; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class WorkApplication { + + public static void main(String[] args) { + SpringApplication.run(WorkApplication.class); + } +} diff --git a/src/main/java/com/bwie/common/MsgDTO.java b/src/main/java/com/bwie/common/MsgDTO.java new file mode 100644 index 0000000..b4a0e03 --- /dev/null +++ b/src/main/java/com/bwie/common/MsgDTO.java @@ -0,0 +1,38 @@ +package com.bwie.common; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@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/src/main/java/com/bwie/common/LoginRequest.java b/src/main/java/com/bwie/common/request/LoginRequest.java similarity index 77% rename from src/main/java/com/bwie/common/LoginRequest.java rename to src/main/java/com/bwie/common/request/LoginRequest.java index 64eb688..63f9109 100644 --- a/src/main/java/com/bwie/common/LoginRequest.java +++ b/src/main/java/com/bwie/common/request/LoginRequest.java @@ -1,4 +1,4 @@ -package com.bwie.common; +package com.bwie.common.request; import lombok.Data; diff --git a/src/main/java/com/bwie/common/request/RequestDTO.java b/src/main/java/com/bwie/common/request/RequestDTO.java new file mode 100644 index 0000000..de88b20 --- /dev/null +++ b/src/main/java/com/bwie/common/request/RequestDTO.java @@ -0,0 +1,93 @@ +package com.bwie.common.request; + +/** + * @author 冯凯 + * @version 1.0 + * @description: TODO + * @date 2023/9/29 13:56 + */ + +import com.alibaba.fastjson.annotation.JSONField; +import com.bwie.common.MsgDTO; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 请求参数 + * 对应生成的 JSON 结构参考 resources/demo-json/request.json + */ +@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/src/main/java/com/bwie/common/response/ResponseDTO.java b/src/main/java/com/bwie/common/response/ResponseDTO.java new file mode 100644 index 0000000..b4436fb --- /dev/null +++ b/src/main/java/com/bwie/common/response/ResponseDTO.java @@ -0,0 +1,112 @@ +package com.bwie.common.response; + +import com.bwie.common.MsgDTO; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 返回参数 + * 对应生成的 JSON 结构参考 resources/demo-json/response.json + */ +@NoArgsConstructor +@Data +public class ResponseDTO { + + @JsonProperty("header") + private HeaderDTO header; + @JsonProperty("payload") + private PayloadDTO payload; + + @NoArgsConstructor + @Data + public static class HeaderDTO { + /** + * 错误码,0表示正常,非0表示出错 + */ + @JsonProperty("code") + private Integer code; + /** + * 会话是否成功的描述信息 + */ + @JsonProperty("message") + private String message; + /** + * 会话的唯一id,用于讯飞技术人员查询服务端会话日志使用,出现调用错误时建议留存该字段 + */ + @JsonProperty("sid") + private String sid; + /** + * 会话状态,取值为[0,1,2];0代表首次结果;1代表中间结果;2代表最后一个结果 + */ + @JsonProperty("status") + private Integer status; + } + + @NoArgsConstructor + @Data + public static class PayloadDTO { + @JsonProperty("choices") + private ChoicesDTO choices; + /** + * 在最后一次结果返回 + */ + @JsonProperty("usage") + private UsageDTO usage; + + @NoArgsConstructor + @Data + public static class ChoicesDTO { + /** + * 文本响应状态,取值为[0,1,2]; 0代表首个文本结果;1代表中间文本结果;2代表最后一个文本结果 + */ + @JsonProperty("status") + private Integer status; + /** + * 返回的数据序号,取值为[0,9999999] + */ + @JsonProperty("seq") + private Integer seq; + /** + * 响应文本 + */ + @JsonProperty("text") + private List text; + + } + + @NoArgsConstructor + @Data + public static class UsageDTO { + @JsonProperty("text") + private TextDTO text; + + @NoArgsConstructor + @Data + public static class TextDTO { + /** + * 保留字段,可忽略 + */ + @JsonProperty("question_tokens") + private Integer questionTokens; + /** + * 包含历史问题的总tokens大小 + */ + @JsonProperty("prompt_tokens") + private Integer promptTokens; + /** + * 回答的tokens大小 + */ + @JsonProperty("completion_tokens") + private Integer completionTokens; + /** + * prompt_tokens和completion_tokens的和,也是本次交互计费的tokens大小 + */ + @JsonProperty("total_tokens") + private Integer totalTokens; + } + } + } +} diff --git a/src/main/java/com/bwie/component/XfXhStreamClient.java b/src/main/java/com/bwie/component/XfXhStreamClient.java new file mode 100644 index 0000000..dcdc847 --- /dev/null +++ b/src/main/java/com/bwie/component/XfXhStreamClient.java @@ -0,0 +1,153 @@ +package com.bwie.component; + +import com.alibaba.fastjson.JSONObject; + +import com.bwie.common.MsgDTO; +import com.bwie.common.request.RequestDTO; +import com.bwie.config.XfXhConfig; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; +import org.java_websocket.WebSocket; +import org.java_websocket.WebSocketListener; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.*; + + +@Component +@Slf4j +public class XfXhStreamClient { + + /** + * @author fst + */ + @Resource + private XfXhConfig xfXhConfig; + + @Value("${xfxh.QPS}") + private int connectionTokenCount; + + /** + * 获取令牌 + */ + public static int GET_TOKEN_STATUS = 0; + /** + * 归还令牌 + */ + public static int BACK_TOKEN_STATUS = 1; + + /** + * 操作令牌 + * + * @param status 0-获取令牌 1-归还令牌 + * @return 是否操作成功 + */ + public synchronized boolean operateToken(int status) { + if (status == GET_TOKEN_STATUS) { + // 获取令牌 + if (connectionTokenCount != 0) { + // 说明还有令牌,将令牌数减一 + connectionTokenCount -= 1; + return true; + } else { + return false; + } + } else { + // 放回令牌 + connectionTokenCount += 1; + return true; + } + } + + /** + * 发送消息 + * + * @param uid 每个用户的id,用于区分不同用户 + * @param msgList 发送给大模型的消息,可以包含上下文内容 + * @return 获取websocket连接,以便于我们在获取完整大模型回复后手动关闭连接 + */ + public WebSocket sendMsg(String uid, List msgList, WebSocketListener listener) { + // 获取鉴权url + String authUrl = this.getAuthUrl(); + // 鉴权方法生成失败,直接返回 null + if (authUrl == null) { + return null; + } + OkHttpClient okHttpClient = new OkHttpClient.Builder().build(); + // 将 https/http 连接替换为 ws/wss 连接 + String url = authUrl.replace("http://", "ws://").replace("https://", "wss://"); + Request request = new Request.Builder().url(url).build(); + // 建立 wss 连接 + WebSocket webSocket = okHttpClient.newWebSocket(request, listener); + // 组装请求参数 + RequestDTO requestDTO = getRequestParam(uid, msgList); + // 发送请求 + webSocket.send(JSONObject.toJSONString(requestDTO)); + return webSocket; + } + + /** + * 生成鉴权方法,具体实现不用关心,这是讯飞官方定义的鉴权方式 + * + * @return 鉴权访问大模型的路径 + */ + public String getAuthUrl() { + try { + URL url = new URL(xfXhConfig.getHostUrl()); + // 时间 + SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + format.setTimeZone(TimeZone.getTimeZone("GMT")); + String date = format.format(new Date()); + // 拼接 + String preStr = "host: " + url.getHost() + "\n" + + "date: " + date + "\n" + + "GET " + url.getPath() + " HTTP/1.1"; + // SHA256加密 + Mac mac = Mac.getInstance("hmacsha256"); + SecretKeySpec spec = new SecretKeySpec(xfXhConfig.getApiSecret().getBytes(StandardCharsets.UTF_8), "hmacsha256"); + mac.init(spec); + + byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8)); + // Base64加密 + String sha = Base64.getEncoder().encodeToString(hexDigits); + // 拼接 + String authorizationOrigin = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", xfXhConfig.getApiKey(), "hmac-sha256", "host date request-line", sha); + // 拼接地址 + HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder(). + addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorizationOrigin.getBytes(StandardCharsets.UTF_8))). + addQueryParameter("date", date). + addQueryParameter("host", url.getHost()). + build(); + + return httpUrl.toString(); + } catch (Exception e) { + log.error("鉴权方法中发生错误:" + e.getMessage()); + return null; + } + } + + /** + * 获取请求参数 + * + * @param uid 每个用户的id,用于区分不同用户 + * @param msgList 发送给大模型的消息,可以包含上下文内容 + * @return 请求DTO,该 DTO 转 json 字符串后生成的格式参考 resources/demo-json/request.json + */ + public RequestDTO getRequestParam(String uid, List msgList) { + RequestDTO requestDTO = new RequestDTO(); + requestDTO.setHeader(new RequestDTO.HeaderDTO(xfXhConfig.getAppId(), uid)); + requestDTO.setParameter(new RequestDTO.ParameterDTO(new RequestDTO.ParameterDTO.ChatDTO(xfXhConfig.getDomain(), xfXhConfig.getTemperature(), xfXhConfig.getMaxTokens()))); + requestDTO.setPayload(new RequestDTO.PayloadDTO(new RequestDTO.PayloadDTO.MessageDTO(msgList))); + return requestDTO; + } + + + +} diff --git a/src/main/java/com/bwie/config/CorsConfig.java b/src/main/java/com/bwie/config/CorsConfig.java new file mode 100644 index 0000000..35f906c --- /dev/null +++ b/src/main/java/com/bwie/config/CorsConfig.java @@ -0,0 +1,24 @@ +package com.bwie.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + + +/** + * @author 冯凯 + * @version 1.0 + * @description: TODO + * @date 2023/10/3 14:43 + */ +@Configuration +public class CorsConfig implements WebMvcConfigurer { + + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/test/sendQuestion") + .allowedOrigins("http://localhost:9528") + .allowedMethods("GET", "POST") + .allowCredentials(true) + .maxAge(3600); + } +} diff --git a/src/main/java/com/bwie/config/XfXhConfig.java b/src/main/java/com/bwie/config/XfXhConfig.java new file mode 100644 index 0000000..b4afe0a --- /dev/null +++ b/src/main/java/com/bwie/config/XfXhConfig.java @@ -0,0 +1,54 @@ +package com.bwie.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author 冯凯 + * @version 1.0 + * @description: TODO + * @date 2023/9/29 13:50 + */ +@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/src/main/java/com/bwie/controller/ChatController.java b/src/main/java/com/bwie/controller/ChatController.java new file mode 100644 index 0000000..b7b848f --- /dev/null +++ b/src/main/java/com/bwie/controller/ChatController.java @@ -0,0 +1,98 @@ +package com.bwie.controller; + +import cn.hutool.core.util.StrUtil; + +import com.bwie.common.MsgDTO; +import com.bwie.component.XfXhStreamClient; +import com.bwie.config.XfXhConfig; +import com.bwie.listener.XfXhWebSocketListener; +import lombok.extern.slf4j.Slf4j; +import org.java_websocket.WebSocket; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Collections; +import java.util.UUID; + +/** + * @author 冯凯 + * @version 1.0 + * @description: TODO + * @date 2023/9/29 14:06 + */ +@RestController +@RequestMapping("/test") +@Slf4j +public class ChatController { + + + @Resource + private XfXhStreamClient xfXhStreamClient; + + @Resource + private XfXhConfig xfXhConfig; + + + /** + * 发送问题 + * + * @param question 问题 + * @return 星火大模型的回答 + */ + @GetMapping("/sendQuestion") + public String sendQuestion(@RequestParam("question") String question) { + // 如果是无效字符串,则不对大模型进行请求 + if (StrUtil.isBlank(question)) { + return "无效问题,请重新输入"; + } + // 获取连接令牌 + if (!xfXhStreamClient.operateToken(XfXhStreamClient.GET_TOKEN_STATUS)) { + return "当前大模型连接数过多,请稍后再试"; + } + + // 创建消息对象 + 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 "大模型响应超时,请联系管理员"; + } + // 响应大模型的答案 + System.out.println(listener.getAnswer().toString()); + 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/src/main/java/com/bwie/controller/UserController.java b/src/main/java/com/bwie/controller/UserController.java index bc3892a..f074150 100644 --- a/src/main/java/com/bwie/controller/UserController.java +++ b/src/main/java/com/bwie/controller/UserController.java @@ -1,6 +1,6 @@ package com.bwie.controller; -import com.bwie.common.LoginRequest; +import com.bwie.common.request.LoginRequest; import com.bwie.common.Result; import com.bwie.service.impl.UserServiceImpl; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/com/bwie/listener/XfXhWebSocketListener.java b/src/main/java/com/bwie/listener/XfXhWebSocketListener.java new file mode 100644 index 0000000..5435448 --- /dev/null +++ b/src/main/java/com/bwie/listener/XfXhWebSocketListener.java @@ -0,0 +1,72 @@ +package com.bwie.listener; + +import com.alibaba.fastjson.JSONObject; +import com.bwie.common.MsgDTO; +import com.bwie.common.response.ResponseDTO; +import lombok.extern.slf4j.Slf4j; +import okhttp3.Response; +import okhttp3.WebSocket; +import okhttp3.WebSocketListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author 冯凯 + * @version 1.0 + * @description: TODO + * @date 2023/9/29 13:58 + */ +@Slf4j +public class XfXhWebSocketListener extends WebSocketListener { + private StringBuilder answer = new StringBuilder(); + + private boolean wsCloseFlag = false; + + public StringBuilder getAnswer() { + return answer; + } + + public boolean isWsCloseFlag() { + return wsCloseFlag; + } + + @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); + // 将大模型回复的 JSON 文本转为 ResponseDTO 对象 + ResponseDTO responseData = JSONObject.parseObject(text, ResponseDTO.class); + // 如果响应数据中的 header 的 code 值不为 0,则表示响应错误 + if (responseData.getHeader().getCode() != 0) { + // 日志记录 + log.error("发生错误,错误码为:" + responseData.getHeader().getCode() + "; " + "信息:" + responseData.getHeader().getMessage()); + // 设置回答 + this.answer = new StringBuilder("大模型响应错误,请稍后再试"); + // 关闭连接标识 + wsCloseFlag = true; + return; + } + // 将回答进行拼接 + for (MsgDTO msgDTO : responseData.getPayload().getChoices().getText()) { + this.answer.append(msgDTO.getContent()); + } + // 对最后一个文本结果进行处理 + if (2 == responseData.getHeader().getStatus()) { + wsCloseFlag = true; + } + } + + @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); + } +} diff --git a/src/main/java/com/bwie/mapper/UserMapper.java b/src/main/java/com/bwie/mapper/UserMapper.java index 3c8d556..676879f 100644 --- a/src/main/java/com/bwie/mapper/UserMapper.java +++ b/src/main/java/com/bwie/mapper/UserMapper.java @@ -1,6 +1,6 @@ package com.bwie.mapper; -import com.bwie.common.LoginRequest; +import com.bwie.common.request.LoginRequest; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/bwie/service/UserService.java b/src/main/java/com/bwie/service/UserService.java index 8cc56db..17fe14d 100644 --- a/src/main/java/com/bwie/service/UserService.java +++ b/src/main/java/com/bwie/service/UserService.java @@ -1,6 +1,6 @@ package com.bwie.service; -import com.bwie.common.LoginRequest; +import com.bwie.common.request.LoginRequest; import com.bwie.common.Result; public interface UserService { diff --git a/src/main/java/com/bwie/service/impl/UserServiceImpl.java b/src/main/java/com/bwie/service/impl/UserServiceImpl.java index c262134..3d4c32c 100644 --- a/src/main/java/com/bwie/service/impl/UserServiceImpl.java +++ b/src/main/java/com/bwie/service/impl/UserServiceImpl.java @@ -1,7 +1,7 @@ package com.bwie.service.impl; import com.bwie.annotation.Idempotent; -import com.bwie.common.LoginRequest; +import com.bwie.common.request.LoginRequest; import com.bwie.common.Result; import com.bwie.mapper.UserMapper; import com.bwie.service.UserService; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 45dcc4d..ec66547 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -9,7 +9,7 @@ spring: password: root name: defaultDataSource mybatis: - mapper-locations: mappers/*xml + mapper-locations: mapper/*xml mybatis: configuration: map-underscore-to-camel-case: true @@ -28,8 +28,8 @@ xfxh: # 允许同时连接大模型的 websocket 数,如果是普通(免费)用户为 2,超过这个数连接响应会报错,具体参考官网。 QPS: 2 # 用于权限验证,从服务接口认证信息中获取 - appId: 4c5ea24c + appId: 3a5er24h # 用于权限验证,从服务接口认证信息中获取 - apiKey: d53d6f5aae8cfee01420eeff6584057f + apiKey: d2hu6f5ace8fdea0982a0eaff658408dh # 用于权限验证,从服务接口认证信息中获取 - apiSecret: Mzg3YTYxZjYyYTE0MTdiOTMyZTdlMTFi + apiSecret: Cst3AJIxEjDyCKQ0MTdiOQIyKIdlLOAi diff --git a/src/main/resources/mapper/UserMapper.xml b/src/main/resources/mapper/UserMapper.xml index 4073a41..c5e4ac9 100644 --- a/src/main/resources/mapper/UserMapper.xml +++ b/src/main/resources/mapper/UserMapper.xml @@ -4,7 +4,7 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - select *from t_user where user_name=#{userName} and user_pwd=#{userPwd} diff --git a/target/classes/com/bwie/test/Test01.class b/target/classes/com/bwie/test/Test01.class deleted file mode 100644 index d9f6315d1166187fe29a09723ba2822610c08113..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 652 zcmZuuO>YuW6g_V~fC8mRJ5`jbU6|01Fjf;{)RGtz6AWsi4V!L!z)SlG^M=41?GNY= zQ8#YfxYD@b2e|j|sOQlpZk%N9efQjZ&OLAD=kFg200-DEB0#-}>$s6eBabbC++%ID z?FjhIoxVWuG#x2{wVpQWWtI%o>_`qKL~6ZsC?|b6)2_Y*1AD6H0-L>In#6VC zov6N^YwmnvOlqaosUfk^OJ^tXIHPyQskUks%c)+j=HlX;G@A|8GwrOGF8s8{@|`Rr zL@tk;W!%DTfsOwe7pS_?cp}Y7{Aw^(Ln~1E2fdK?lpg8Y-K)!cVH-Zbtb05VM2<1f zDrOeU;qEtxugi9U(Y1jBRv60{11O@zO0Zs~h$Am3nPYzFANn1?9r*1q3ilSl=o6Za zDEx>9<6acD-hPL77==;r0V|DmaPEuqP<;OLYwHWy9`^vPrFw}~nX0SQuV5W(sH2KI zxPpDuXm%a( diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties deleted file mode 100644 index 0c2efea..0000000 --- a/target/maven-archiver/pom.properties +++ /dev/null @@ -1,5 +0,0 @@ -#Generated by Maven -#Wed Oct 04 22:55:50 CST 2023 -version=1.0-SNAPSHOT -groupId=com.bwie -artifactId=test-10.01 diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index 408068a..00ff73f 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -1 +1,4 @@ -com\bwie\test\Test01.class +com\bwie\common\Result.class +com\bwie\service\UserService.class +com\bwie\common\request\LoginRequest.class +META-INF\spring-configuration-metadata.json diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst index e00223c..c328f80 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -1 +1,17 @@ +D:\lv6\test-10.01\src\main\java\com\bwie\common\response\ResponseDTO.java +D:\lv6\test-10.01\src\main\java\com\bwie\controller\ChatController.java +D:\lv6\test-10.01\src\main\java\com\bwie\config\CorsConfig.java +D:\lv6\test-10.01\src\main\java\com\bwie\service\UserService.java +D:\lv6\test-10.01\src\main\java\com\bwie\mapper\UserMapper.java +D:\lv6\test-10.01\src\main\java\com\bwie\common\Result.java +D:\lv6\test-10.01\src\main\java\com\bwie\controller\UserController.java +D:\lv6\test-10.01\src\main\java\com\bwie\common\request\LoginRequest.java +D:\lv6\test-10.01\src\main\java\com\bwie\service\impl\UserServiceImpl.java +D:\lv6\test-10.01\src\main\java\com\bwie\common\MsgDTO.java +D:\lv6\test-10.01\src\main\java\com\bwie\annotation\Idempotent.java +D:\lv6\test-10.01\src\main\java\com\bwie\common\request\RequestDTO.java +D:\lv6\test-10.01\src\main\java\com\bwie\component\XfXhStreamClient.java +D:\lv6\test-10.01\src\main\java\com\bwie\aspect\IdempotentAspect.java +D:\lv6\test-10.01\src\main\java\com\bwie\config\XfXhConfig.java D:\lv6\test-10.01\src\main\java\com\bwie\test\Test01.java +D:\lv6\test-10.01\src\main\java\com\bwie\WorkApplication.java diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst deleted file mode 100644 index e69de29..0000000 diff --git a/target/test-10.01-1.0-SNAPSHOT.jar b/target/test-10.01-1.0-SNAPSHOT.jar deleted file mode 100644 index 58af6c8e0a83dee37c0d74dd88d055990fba7b18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2703 zcmWIWW@h1H0D)iIT*AQ&D8UJ&eO*Hwbv^yu^aG&EI2e8cm08~J`j-QgZU$lzWM#gN zex7cw!6ACSZl8V6oc8h7)w{^+t*dqJ%=yhh23L$9JT21kI(I_HTi1z${mGKBDPr0O zR4R7P@iH#e15SOcohKz%a_#F(U0KO>tSYVQm;kTl zt~kw`3f4MbcpmZgHtwp}$pCX5rYBf{u1n6(g}Wb91<0Eq6-nipsd$v}AuB6MEiQqp zp?gq)nXxD*_xdh6#*3f&#Jr*D$!7xpjh4B~n*7L689*bAP&XGk`0;-2>B z-oBfapP${dud9t`usG7kFJ3BtyKN~d+6MFC}38)r-|r? zS?YK1u4}kZGc$Iw%bPQEKg9Grsl48E#q#0K&=l)aJuI)*3niB>`Bk;f^4&(mjZ?#p zxApeM*;w-)=iF=Tw>5NgfM2QEtmePh3yq{#Ew?I--1X(M)amV;c=&%ZOOz$J*EppeeDk)p z^~a=Gammk;5l6U^e@{l4FfR6Orpt7E%txmNX$-zV07G;=>&w(NPpPdT%SB0(MVyJx=L zI<+U}FEj2W$PY{n@O+e;SeBXxPdb>XQ36vjFmdV;NSw-ebb->UuAzaRfg#*l4u-qH zOk64RWBz1dYK`J$V9+AYfC8XXDspr7hQ;RJG7zbK9S15$!F?x)-FhR`aQ1m%s$`d@Qs1}(ViKv^j+N+9;!SYDfLF_Z?%$XywECN z2jiuIDPdig9w^*-%y!Xuv1L@v?~2_&YKo_`?at`ej5zC(Xx3sp^{r_or~Q7G_(J2Q zk9?JPnEf}s?jtwxj=Ic-O%)~&1Xuo?Kj(X<^|bUItNG3@R(>QVB6F!my)xAMa-+AW z*0rWPk7OLIuUuHZkgr#xLp9#?(l;I>UZ0sk3jYH|ugFfBGILt*&1-)j-`;xshs=4u zYj5MsL@VxQG+bJEPOifv(kk~7kGtK>s#^-hS5mKM>7JHd^+9jD<-R3PEKhbazgG>c zTI^sU&|A=BKc{+HwX>Y3`V^*Jsd`TJZ-weM)EKH*T=3iTdbOOCQe<%Qjk2~m79ZYC z^apOBYM_E#JqVxN}Zkj9+ZKv+9~fq7qI_rw_63ZA>UfsHv%kxm>n@-->IkPV=WLsWrx-C z&l(@!wLZKebDEt+dU$$zDtDd=>h3cB{5gmBD^E%DUm4~m+ds|~J1=#A^5(V)&YAqV z`0J!o#=(_4g}S|rE(=ZeZfH_nc~o^*8(S4y+nyL;6~@RU!i>8n2KoXB1Q^~rf@pYo zg3yM&W(Fw+fhCRVKoYJEsh&odfLR)WYEK9NS$q`8gw&