配置模块,加写完后台
parent
88d4dba7ee
commit
7b1492be0a
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="AliAccessStaticViaInstance" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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<MsgDTO> text;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -125,9 +125,37 @@
|
|||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.a812086325</groupId>
|
||||
<artifactId>xfxh-java</artifactId>
|
||||
<version>1.0</version>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.18</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.67</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.java-websocket</groupId>
|
||||
<artifactId>Java-WebSocket</artifactId>
|
||||
<version>1.3.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.10.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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<MsgDTO> 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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue