mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2026-01-03 12:05:28 +08:00
【jeecgboot 3.7.0里程碑版本发布——合并springboot3sas分支】
Merge remote-tracking branch 'origin/springboot3' into springboot3_sas # Conflicts: # .gitignore # db/tables_nacos.sql # jeecg-boot-base-core/pom.xml # jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/AutoLogAspect.java # jeecg-boot-base-core/src/main/java/org/jeecg/common/exception/JeecgBootExceptionHandler.java # jeecg-boot-base-core/src/main/java/org/jeecg/config/DruidWallConfigRegister.java # jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java # jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroRealm.java # jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/filters/JwtFilter.java # jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/impl/BaseCommonServiceImpl.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysAnnouncementController.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDepartController.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDepartRoleController.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDictController.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysPermissionController.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysTableWhiteListController.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysTenantController.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysUserController.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysAnnouncementServiceImpl.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysDepartServiceImpl.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysTenantPackServiceImpl.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysTenantServiceImpl.java # jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysUserDepartServiceImpl.java # jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml # jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml # jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml # pom.xml
This commit is contained in:
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>jeecg-boot-parent</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>3.6.1</version>
|
||||
<version>3.7.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ public class JcloudDemoProviderController {
|
||||
private JcloudDemoService jcloudDemoService;
|
||||
|
||||
@GetMapping("/getMessage")
|
||||
public String getMessage(@RequestParam String name) {
|
||||
public String getMessage(@RequestParam(name = "name") String name) {
|
||||
String msg = jcloudDemoService.getMessage(name);
|
||||
log.info(" 微服务被调用:{} ",msg);
|
||||
return msg;
|
||||
|
||||
34
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/gpt/cache/LocalCache.java
vendored
Normal file
34
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/gpt/cache/LocalCache.java
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
package org.jeecg.modules.demo.gpt.cache;
|
||||
|
||||
import cn.hutool.cache.CacheUtil;
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.hutool.core.date.DateUnit;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
|
||||
/**
|
||||
* 聊天记录本地缓存
|
||||
* @author chenrui
|
||||
* @date 2024/1/26 20:06
|
||||
*/
|
||||
public class LocalCache {
|
||||
/**
|
||||
* 缓存时长
|
||||
*/
|
||||
public static final long TIMEOUT = 5 * DateUnit.MINUTE.getMillis();
|
||||
/**
|
||||
* 清理间隔
|
||||
*/
|
||||
private static final long CLEAN_TIMEOUT = 5 * DateUnit.MINUTE.getMillis();
|
||||
/**
|
||||
* 缓存对象
|
||||
*/
|
||||
public static final TimedCache<String, Object> CACHE = CacheUtil.newTimedCache(TIMEOUT);
|
||||
|
||||
static {
|
||||
//启动定时任务
|
||||
CACHE.schedulePrune(CLEAN_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
//update-end---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
@ -0,0 +1,74 @@
|
||||
package org.jeecg.modules.demo.gpt.controller;
|
||||
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.modules.demo.gpt.service.ChatService;
|
||||
import org.jeecg.modules.demo.gpt.vo.ChatHistoryVO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
|
||||
/**
|
||||
* @Description: chatGpt-聊天接口
|
||||
* @Author: chenrui
|
||||
* @Date: 2024/1/9 16:30
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/test/ai/chat")
|
||||
public class ChatController {
|
||||
|
||||
@Autowired
|
||||
ChatService chatService;
|
||||
|
||||
/**
|
||||
* 创建sse连接
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/send")
|
||||
public SseEmitter createConnect(@RequestParam(name = "topicId", required = false) String topicId, @RequestParam(name = "message", required = true) String message) {
|
||||
SseEmitter sse = chatService.createChat();
|
||||
chatService.sendMessage(topicId, message);
|
||||
return sse;
|
||||
}
|
||||
|
||||
//update-begin---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
/**
|
||||
* 保存聊天记录
|
||||
* @param chatHistoryVO
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/2/22 13:54
|
||||
*/
|
||||
@PostMapping(value = "/history/save")
|
||||
@ResponseBody
|
||||
public Result<?> saveHistory(@RequestBody ChatHistoryVO chatHistoryVO) {
|
||||
return chatService.saveHistory(chatHistoryVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询聊天记录
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/2/22 14:03
|
||||
*/
|
||||
@GetMapping(value = "/history/get")
|
||||
@ResponseBody
|
||||
public Result<ChatHistoryVO> getHistoryByTopic() {
|
||||
return chatService.getHistoryByTopic();
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
|
||||
/**
|
||||
* 关闭连接
|
||||
*/
|
||||
@GetMapping(value = "/close")
|
||||
public void closeConnect() {
|
||||
chatService.closeChat();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
@ -0,0 +1,136 @@
|
||||
package org.jeecg.modules.demo.gpt.listeners;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse;
|
||||
import com.unfbx.chatgpt.entity.chat.Message;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okhttp3.sse.EventSource;
|
||||
import okhttp3.sse.EventSourceListener;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
/**
|
||||
* OpenAI的SSE监听
|
||||
* @author chenrui
|
||||
* @date 2024/1/26 20:06
|
||||
*/
|
||||
@Slf4j
|
||||
public class OpenAISSEEventSourceListener extends EventSourceListener {
|
||||
|
||||
private long tokens;
|
||||
|
||||
private SseEmitter sseEmitter;
|
||||
|
||||
private String topicId;
|
||||
|
||||
public OpenAISSEEventSourceListener(SseEmitter sseEmitter) {
|
||||
this.sseEmitter = sseEmitter;
|
||||
}
|
||||
|
||||
public OpenAISSEEventSourceListener(String topicId,SseEmitter sseEmitter){
|
||||
this.topicId = topicId;
|
||||
this.sseEmitter = sseEmitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onOpen(@NotNull EventSource eventSource, @NotNull Response response) {
|
||||
log.info("OpenAI建立sse连接...");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void onEvent(@NotNull EventSource eventSource, String id, String type, @NotNull String data) {
|
||||
log.debug("OpenAI返回数据:{}", data);
|
||||
tokens += 1;
|
||||
if (data.equals("[DONE]")) {
|
||||
log.info("OpenAI返回数据结束了");
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[TOKENS]")
|
||||
.data("<br/><br/>tokens:" + tokens())
|
||||
.reconnectTime(3000));
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[DONE]")
|
||||
.data("[DONE]")
|
||||
.reconnectTime(3000));
|
||||
// 传输完成后自动关闭sse
|
||||
sseEmitter.complete();
|
||||
return;
|
||||
}
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
ChatCompletionResponse completionResponse = mapper.readValue(data, ChatCompletionResponse.class); // 读取Json
|
||||
try {
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id(this.topicId)
|
||||
.data(completionResponse.getChoices().get(0).getDelta())
|
||||
.reconnectTime(3000));
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(),e);
|
||||
eventSource.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClosed(@NotNull EventSource eventSource) {
|
||||
log.info("流式输出返回值总共{}tokens", tokens() - 2);
|
||||
log.info("OpenAI关闭sse连接...");
|
||||
}
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void onFailure(@NotNull EventSource eventSource, Throwable t, Response response) {
|
||||
String errMsg = "";
|
||||
ResponseBody body = null == response ? null:response.body();
|
||||
if (Objects.nonNull(body)) {
|
||||
log.error("OpenAI sse连接异常data:{},异常:{}", body.string(), t.getMessage());
|
||||
errMsg = body.string();
|
||||
} else {
|
||||
log.error("OpenAI sse连接异常data:{},异常:{}", response, t.getMessage());
|
||||
errMsg = t.getMessage();
|
||||
}
|
||||
eventSource.cancel();
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[ERR]")
|
||||
.data(Message.builder().content(explainErr(errMsg)).build())
|
||||
.reconnectTime(3000));
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[DONE]")
|
||||
.data("[DONE]")
|
||||
.reconnectTime(3000));
|
||||
sseEmitter.complete();
|
||||
}
|
||||
|
||||
private String explainErr(String errMsg){
|
||||
if(StringUtils.isEmpty(errMsg)){
|
||||
return "";
|
||||
}
|
||||
if(errMsg.contains("Rate limit")){
|
||||
return "请求频率太快了,请等待20秒再试.";
|
||||
}
|
||||
return errMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* tokens
|
||||
* @return
|
||||
*/
|
||||
public long tokens() {
|
||||
return tokens;
|
||||
}
|
||||
}
|
||||
|
||||
//update-end---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
@ -0,0 +1,56 @@
|
||||
package org.jeecg.modules.demo.gpt.service;
|
||||
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.modules.demo.gpt.vo.ChatHistoryVO;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
|
||||
/**
|
||||
* AI助手聊天Service
|
||||
* @author chenrui
|
||||
* @date 2024/1/26 20:08
|
||||
*/
|
||||
public interface ChatService {
|
||||
/**
|
||||
* 创建SSE
|
||||
* @return
|
||||
*/
|
||||
SseEmitter createChat();
|
||||
|
||||
/**
|
||||
* 关闭SSE
|
||||
*/
|
||||
void closeChat();
|
||||
|
||||
/**
|
||||
* 客户端发送消息到服务端
|
||||
*
|
||||
* @param topicId
|
||||
* @param message
|
||||
* @author chenrui
|
||||
* @date 2024/1/26 20:01
|
||||
*/
|
||||
void sendMessage(String topicId, String message);
|
||||
|
||||
//update-begin---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
/**
|
||||
* 保存聊天记录
|
||||
* @param chatHistoryVO
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/2/22 13:37
|
||||
*/
|
||||
Result<?> saveHistory(ChatHistoryVO chatHistoryVO);
|
||||
|
||||
/**
|
||||
* 查询聊天记录
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/2/22 13:59
|
||||
*/
|
||||
Result<ChatHistoryVO> getHistoryByTopic();
|
||||
//update-end---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
}
|
||||
|
||||
//update-end---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
@ -0,0 +1,199 @@
|
||||
package org.jeecg.modules.demo.gpt.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.unfbx.chatgpt.OpenAiStreamClient;
|
||||
import com.unfbx.chatgpt.entity.chat.ChatCompletion;
|
||||
import com.unfbx.chatgpt.entity.chat.Message;
|
||||
import com.unfbx.chatgpt.exception.BaseException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.UUIDGenerator;
|
||||
import org.jeecg.modules.demo.gpt.cache.LocalCache;
|
||||
import org.jeecg.modules.demo.gpt.listeners.OpenAISSEEventSourceListener;
|
||||
import org.jeecg.modules.demo.gpt.service.ChatService;
|
||||
import org.jeecg.modules.demo.gpt.vo.ChatHistoryVO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
|
||||
/**
|
||||
* AI助手聊天Service
|
||||
* @author chenrui
|
||||
* @date 2024/1/26 20:07
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ChatServiceImpl implements ChatService {
|
||||
|
||||
//update-begin---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
private static final String CACHE_KEY_PREFIX = "ai:chart:";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final String CACHE_KEY_MSG_CONTEXT = "msg_content";
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final String CACHE_KEY_MSG_HISTORY = "msg_history";
|
||||
|
||||
@Autowired
|
||||
RedisTemplate redisTemplate;
|
||||
//update-end---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
|
||||
private OpenAiStreamClient openAiStreamClient = null;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240131 for:[QQYUN-8212]fix 没有配置启动报错------------
|
||||
public ChatServiceImpl() {
|
||||
try {
|
||||
this.openAiStreamClient = SpringContextUtils.getBean(OpenAiStreamClient.class);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 防止client不能成功注入
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/2/3 23:08
|
||||
*/
|
||||
private OpenAiStreamClient ensureClient(){
|
||||
if(null == this.openAiStreamClient){
|
||||
this.openAiStreamClient = SpringContextUtils.getBean(OpenAiStreamClient.class);
|
||||
}
|
||||
return this.openAiStreamClient;
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240131 for:[QQYUN-8212]fix 没有配置启动报错------------
|
||||
|
||||
private String getUserId() {
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
return sysUser.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SseEmitter createChat() {
|
||||
String uid = getUserId();
|
||||
//默认30秒超时,设置为0L则永不超时
|
||||
SseEmitter sseEmitter = new SseEmitter(-0L);
|
||||
//完成后回调
|
||||
sseEmitter.onCompletion(() -> {
|
||||
log.info("[{}]结束连接...................",uid);
|
||||
LocalCache.CACHE.remove(uid);
|
||||
});
|
||||
//超时回调
|
||||
sseEmitter.onTimeout(() -> {
|
||||
log.info("[{}]连接超时...................", uid);
|
||||
});
|
||||
//异常回调
|
||||
sseEmitter.onError(
|
||||
throwable -> {
|
||||
try {
|
||||
log.info("[{}]连接异常,{}", uid, throwable.toString());
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id(uid)
|
||||
.name("发生异常!")
|
||||
.data(Message.builder().content("发生异常请重试!").build())
|
||||
.reconnectTime(3000));
|
||||
LocalCache.CACHE.put(uid, sseEmitter);
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(),e);
|
||||
}
|
||||
}
|
||||
);
|
||||
try {
|
||||
sseEmitter.send(SseEmitter.event().reconnectTime(5000));
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(),e);
|
||||
}
|
||||
LocalCache.CACHE.put(uid, sseEmitter);
|
||||
log.info("[{}]创建sse连接成功!", uid);
|
||||
return sseEmitter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeChat() {
|
||||
String uid = getUserId();
|
||||
SseEmitter sse = (SseEmitter) LocalCache.CACHE.get(uid);
|
||||
if (sse != null) {
|
||||
sse.complete();
|
||||
//移除
|
||||
LocalCache.CACHE.remove(uid);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String topicId, String message) {
|
||||
String uid = getUserId();
|
||||
if (StrUtil.isBlank(message)) {
|
||||
log.info("参数异常,message为null");
|
||||
throw new BaseException("参数异常,message不能为空~");
|
||||
}
|
||||
if (StrUtil.isBlank(topicId)) {
|
||||
topicId = UUIDGenerator.generate();
|
||||
}
|
||||
//update-begin---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
log.info("话题id:{}", topicId);
|
||||
String cacheKey = CACHE_KEY_PREFIX + uid + "_" + topicId;
|
||||
String messageContext = (String) redisTemplate.opsForHash().get(cacheKey, CACHE_KEY_MSG_CONTEXT);
|
||||
List<Message> msgHistory = new ArrayList<>();
|
||||
if (StrUtil.isNotBlank(messageContext)) {
|
||||
List<Message> messages = JSONArray.parseArray(messageContext, Message.class);
|
||||
msgHistory = messages == null ? new ArrayList<>() : messages;
|
||||
}
|
||||
Message currentMessage = Message.builder().content(message).role(Message.Role.USER).build();
|
||||
msgHistory.add(currentMessage);
|
||||
|
||||
SseEmitter sseEmitter = (SseEmitter) LocalCache.CACHE.get(uid);
|
||||
if (sseEmitter == null) {
|
||||
log.info("聊天消息推送失败uid:[{}],没有创建连接,请重试。", uid);
|
||||
throw new JeecgBootException("聊天消息推送失败uid:[{}],没有创建连接,请重试。~");
|
||||
}
|
||||
OpenAISSEEventSourceListener openAIEventSourceListener = new OpenAISSEEventSourceListener(topicId, sseEmitter);
|
||||
ChatCompletion completion = ChatCompletion
|
||||
.builder()
|
||||
.messages(msgHistory)
|
||||
.model(ChatCompletion.Model.GPT_3_5_TURBO.getName())
|
||||
.build();
|
||||
ensureClient().streamChatCompletion(completion, openAIEventSourceListener);
|
||||
redisTemplate.opsForHash().put(cacheKey, CACHE_KEY_MSG_CONTEXT, JSONUtil.toJsonStr(msgHistory));
|
||||
//update-end---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
Result.ok(completion.tokens());
|
||||
}
|
||||
|
||||
//update-begin---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
@Override
|
||||
public Result<?> saveHistory(ChatHistoryVO chatHistoryVO) {
|
||||
String uid = getUserId();
|
||||
String cacheKey = CACHE_KEY_PREFIX + CACHE_KEY_MSG_HISTORY + ":" + uid;
|
||||
redisTemplate.opsForValue().set(cacheKey, chatHistoryVO.getContent());
|
||||
return Result.OK("保存成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<ChatHistoryVO> getHistoryByTopic() {
|
||||
String uid = getUserId();
|
||||
String cacheKey = CACHE_KEY_PREFIX + CACHE_KEY_MSG_HISTORY + ":" + uid;
|
||||
String historyContent = (String) redisTemplate.opsForValue().get(cacheKey);
|
||||
ChatHistoryVO chatHistoryVO = new ChatHistoryVO();
|
||||
chatHistoryVO.setContent(historyContent);
|
||||
return Result.OK(chatHistoryVO);
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
}
|
||||
|
||||
//update-end---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
@ -0,0 +1,25 @@
|
||||
package org.jeecg.modules.demo.gpt.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @Description: 聊天记录
|
||||
* @Author: chenrui
|
||||
* @Date: 2024/2/22 13:36
|
||||
*/
|
||||
@Data
|
||||
public class ChatHistoryVO implements Serializable {
|
||||
private static final long serialVersionUID = 3238429500037511283L;
|
||||
|
||||
/**
|
||||
* 话题id
|
||||
*/
|
||||
String topicId;
|
||||
|
||||
/**
|
||||
* 聊天记录内容
|
||||
*/
|
||||
String content;
|
||||
}
|
||||
@ -20,6 +20,7 @@ import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.UUIDGenerator;
|
||||
import org.jeecg.config.shiro.IgnoreAuth;
|
||||
import org.jeecg.modules.demo.test.entity.JeecgDemo;
|
||||
import org.jeecg.modules.demo.test.service.IJeecgDemoService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -227,6 +228,7 @@ public class JeecgDemoController extends JeecgController<JeecgDemo, IJeecgDemoSe
|
||||
* @param modelAndView
|
||||
* @return
|
||||
*/
|
||||
@IgnoreAuth
|
||||
@RequestMapping("/html")
|
||||
public ModelAndView ftl(ModelAndView modelAndView) {
|
||||
modelAndView.setViewName("demo3");
|
||||
|
||||
@ -44,11 +44,11 @@ public class JeecgDemo extends JeecgEntity implements Serializable {
|
||||
private java.util.Date punchTime;
|
||||
/** 工资 */
|
||||
@Schema(description = "工资",example = "0")
|
||||
@Excel(name="工资",width=15)
|
||||
@Excel(name="工资",type = 4,width=15)
|
||||
private java.math.BigDecimal salaryMoney;
|
||||
/** 奖金 */
|
||||
@Schema(description = "奖金",example = "0")
|
||||
@Excel(name="奖金",width=15)
|
||||
@Excel(name="奖金",type = 4,width=15)
|
||||
private java.lang.Double bonusMoney;
|
||||
/** 性别 {男:1,女:2} */
|
||||
@Schema(description = "性别")
|
||||
@ -56,7 +56,7 @@ public class JeecgDemo extends JeecgEntity implements Serializable {
|
||||
private java.lang.String sex;
|
||||
/** 年龄 */
|
||||
@Schema(description = "年龄",example = "0")
|
||||
@Excel(name="年龄",width=15)
|
||||
@Excel(name="年龄",type = 4,width=15)
|
||||
private java.lang.Integer age;
|
||||
/** 生日 */
|
||||
@Schema(description = "生日")
|
||||
|
||||
Reference in New Issue
Block a user