mirror of https://github.com/jeecgboot/jeecg-boot
修复问题:线上ai助手后端内容一次性返回,消息不显示
parent
86cfc18fe8
commit
81b4cbbe35
|
@ -17,6 +17,7 @@ import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenAI的SSE监听
|
* OpenAI的SSE监听
|
||||||
* @author chenrui
|
* @author chenrui
|
||||||
|
@ -49,7 +50,7 @@ public class OpenAISSEEventSourceListener extends EventSourceListener {
|
||||||
this.sseEmitter = sseEmitter;
|
this.sseEmitter = sseEmitter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OpenAISSEEventSourceListener(String topicId,SseEmitter sseEmitter){
|
public OpenAISSEEventSourceListener(String topicId, SseEmitter sseEmitter){
|
||||||
this.topicId = topicId;
|
this.topicId = topicId;
|
||||||
this.sseEmitter = sseEmitter;
|
this.sseEmitter = sseEmitter;
|
||||||
}
|
}
|
||||||
|
@ -102,40 +103,44 @@ public class OpenAISSEEventSourceListener extends EventSourceListener {
|
||||||
try {
|
try {
|
||||||
//update-begin---author:chenrui ---date:20250207 for:[QQYUN-11102/QQYUN-11109]兼容deepseek模型,支持think标签------------
|
//update-begin---author:chenrui ---date:20250207 for:[QQYUN-11102/QQYUN-11109]兼容deepseek模型,支持think标签------------
|
||||||
// 兼容think标签
|
// 兼容think标签
|
||||||
Message delta = completionResponse.getChoices().get(0).getDelta();
|
//update-begin---author:chenrui ---date:20250210 for:判断空,防止反悔的内容为空报错.------------
|
||||||
if (null != delta) {
|
if(null != completionResponse.getChoices()
|
||||||
String content = delta.getContent();
|
&& !completionResponse.getChoices().isEmpty()
|
||||||
if("<think>".equals(content)){
|
&& null != completionResponse.getChoices().get(0)) {
|
||||||
isThinking = true;
|
//update-end---author:chenrui ---date:20250210 for:判断空,防止反悔的内容为空报错.------------
|
||||||
content = "> ";
|
Message delta = completionResponse.getChoices().get(0).getDelta();
|
||||||
delta.setContent(content);
|
if (null != delta) {
|
||||||
}
|
String content = delta.getContent();
|
||||||
if("</think>".equals(content)){
|
if ("<think>".equals(content)) {
|
||||||
isThinking = false;
|
isThinking = true;
|
||||||
content = "\n\n";
|
content = "> ";
|
||||||
delta.setContent(content);
|
|
||||||
}
|
|
||||||
if (isThinking) {
|
|
||||||
if (null != content && content.contains("\n")) {
|
|
||||||
content = "\n> ";
|
|
||||||
delta.setContent(content);
|
delta.setContent(content);
|
||||||
}
|
}
|
||||||
}else {
|
if ("</think>".equals(content)) {
|
||||||
// 响应消息体不记录思考过程
|
isThinking = false;
|
||||||
messageContent += null == content ? "" : content;
|
content = "\n\n";
|
||||||
|
delta.setContent(content);
|
||||||
|
}
|
||||||
|
if (isThinking) {
|
||||||
|
if (null != content && content.contains("\n")) {
|
||||||
|
content = "\n> ";
|
||||||
|
delta.setContent(content);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 响应消息体不记录思考过程
|
||||||
|
messageContent += null == content ? "" : content;
|
||||||
|
}
|
||||||
|
log.info("ai-chat返回数据,发送给前端:" + content);
|
||||||
|
sseEmitter.send(SseEmitter.event()
|
||||||
|
.id(this.topicId)
|
||||||
|
.data(delta)
|
||||||
|
.reconnectTime(3000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
log.info("ai-chat返回数据,发送给前端:" + content);
|
|
||||||
sseEmitter.send(SseEmitter.event()
|
|
||||||
.id(this.topicId)
|
|
||||||
.data(delta)
|
|
||||||
.reconnectTime(3000));
|
|
||||||
}
|
}
|
||||||
//update-end---author:chenrui ---date:20250207 for:[QQYUN-11102/QQYUN-11109]兼容deepseek模型,支持think标签------------
|
//update-end---author:chenrui ---date:20250207 for:[QQYUN-11102/QQYUN-11109]兼容deepseek模型,支持think标签------------
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage(),e);
|
log.error("ai-chat返回数据,发生异常"+e.getMessage(),e);
|
||||||
|
sseEmitter.completeWithError(e);
|
||||||
eventSource.cancel();
|
eventSource.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,7 @@ public class ChatServiceImpl implements ChatService {
|
||||||
//超时回调
|
//超时回调
|
||||||
sseEmitter.onTimeout(() -> {
|
sseEmitter.onTimeout(() -> {
|
||||||
log.info("[{}]连接超时...................", uid);
|
log.info("[{}]连接超时...................", uid);
|
||||||
|
LocalCache.CACHE.remove(uid);
|
||||||
});
|
});
|
||||||
//异常回调
|
//异常回调
|
||||||
sseEmitter.onError(
|
sseEmitter.onError(
|
||||||
|
@ -115,7 +116,7 @@ public class ChatServiceImpl implements ChatService {
|
||||||
.name("发生异常!")
|
.name("发生异常!")
|
||||||
.data(Message.builder().content("发生异常请重试!").build())
|
.data(Message.builder().content("发生异常请重试!").build())
|
||||||
.reconnectTime(3000));
|
.reconnectTime(3000));
|
||||||
LocalCache.CACHE.put(uid, sseEmitter);
|
LocalCache.CACHE.remove(uid);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error(e.getMessage(),e);
|
log.error(e.getMessage(),e);
|
||||||
}
|
}
|
||||||
|
@ -179,6 +180,7 @@ public class ChatServiceImpl implements ChatService {
|
||||||
finalMsgHistory.add(tempMessage);
|
finalMsgHistory.add(tempMessage);
|
||||||
redisTemplate.opsForHash().put(cacheKey, CACHE_KEY_MSG_CONTEXT, JSONUtil.toJsonStr(finalMsgHistory));
|
redisTemplate.opsForHash().put(cacheKey, CACHE_KEY_MSG_CONTEXT, JSONUtil.toJsonStr(finalMsgHistory));
|
||||||
});
|
});
|
||||||
|
log.info("话题:{},开始发送消息~~~", topicId);
|
||||||
ChatCompletion completion = ChatCompletion
|
ChatCompletion completion = ChatCompletion
|
||||||
.builder()
|
.builder()
|
||||||
.messages(msgHistory)
|
.messages(msgHistory)
|
||||||
|
|
|
@ -153,6 +153,7 @@
|
||||||
import presetQuestion from './presetQuestion.vue';
|
import presetQuestion from './presetQuestion.vue';
|
||||||
import { DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
import { DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||||
import { message, Modal, Tabs } from 'ant-design-vue';
|
import { message, Modal, Tabs } from 'ant-design-vue';
|
||||||
|
import { isObject, isString } from '/@/utils/is';
|
||||||
import '../style/github-markdown.less';
|
import '../style/github-markdown.less';
|
||||||
import '../style/highlight.less';
|
import '../style/highlight.less';
|
||||||
import '../style/style.less';
|
import '../style/style.less';
|
||||||
|
@ -250,40 +251,46 @@
|
||||||
// 当从事件源接收到数据时触发
|
// 当从事件源接收到数据时触发
|
||||||
evtSource.onmessage = function (e) {
|
evtSource.onmessage = function (e) {
|
||||||
const data = e.data;
|
const data = e.data;
|
||||||
// console.log(e);
|
let delay = 0;
|
||||||
if (data === '[DONE]') {
|
setTimeout(() => {
|
||||||
updateChatSome(uuid, props.chatData.length - 1, { loading: false });
|
if (data === '[DONE]') {
|
||||||
scrollToBottom();
|
updateChatSome(uuid, props.chatData.length - 1, { loading: false });
|
||||||
handleStop();
|
|
||||||
evtSource.close(); // 关闭连接
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
const _data = JSON.parse(data);
|
|
||||||
const content = _data.content;
|
|
||||||
if (content != undefined) {
|
|
||||||
lastText += content;
|
|
||||||
updateChat(uuid.value, props.chatData.length - 1, {
|
|
||||||
dateTime: new Date().toLocaleString(),
|
|
||||||
text: lastText,
|
|
||||||
inversion: false,
|
|
||||||
error: false,
|
|
||||||
loading: true,
|
|
||||||
conversationOptions: e.lastEventId == '[ERR]' ? null : { conversationId: data.conversationId, parentMessageId: e.lastEventId },
|
|
||||||
requestOptions: { prompt: message, options: { ...options } },
|
|
||||||
});
|
|
||||||
scrollToBottom();
|
|
||||||
} else {
|
|
||||||
updateChatSome(uuid.value, props.chatData.length - 1, { loading: false });
|
|
||||||
scrollToBottom();
|
|
||||||
handleStop();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
updateChatSome(uuid.value, props.chatData.length - 1, { loading: false });
|
|
||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
handleStop();
|
handleStop();
|
||||||
evtSource.close(); // 关闭连接
|
evtSource.close(); // 关闭连接
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const _data = JSON.parse(data);
|
||||||
|
const content = _data.content;
|
||||||
|
if (content != undefined) {
|
||||||
|
lastText += content;
|
||||||
|
updateChat(uuid.value, props.chatData.length - 1, {
|
||||||
|
dateTime: new Date().toLocaleString(),
|
||||||
|
text: lastText,
|
||||||
|
inversion: false,
|
||||||
|
error: false,
|
||||||
|
loading: true,
|
||||||
|
conversationOptions: e.lastEventId == '[ERR]' ? null : { conversationId: data.conversationId, parentMessageId: e.lastEventId },
|
||||||
|
requestOptions: { prompt: message, options: { ...options } },
|
||||||
|
});
|
||||||
|
scrollToBottom();
|
||||||
|
} else {
|
||||||
|
// updateChatSome(uuid.value, props.chatData.length - 1, { loading: false });
|
||||||
|
// scrollToBottom();
|
||||||
|
// handleStop();
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log('ai 聊天:::', error);
|
||||||
|
if (isObject(error) && isString(error.message) && error.message.endsWith('is not valid JSON')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateChatSome(uuid.value, props.chatData.length - 1, { loading: false });
|
||||||
|
scrollToBottom();
|
||||||
|
handleStop();
|
||||||
|
evtSource.close(); // 关闭连接
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}, delay);
|
||||||
};
|
};
|
||||||
// 与事件源的连接无法打开时触发
|
// 与事件源的连接无法打开时触发
|
||||||
evtSource.onerror = function (e) {
|
evtSource.onerror = function (e) {
|
||||||
|
@ -347,6 +354,7 @@
|
||||||
};
|
};
|
||||||
// 停止响应
|
// 停止响应
|
||||||
const handleStop = () => {
|
const handleStop = () => {
|
||||||
|
console.log('ai 聊天:::---停止响应');
|
||||||
if (loading.value) {
|
if (loading.value) {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue