mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 21:13:50 +00:00
@@ -199,13 +199,15 @@ const ChatBox = (
|
||||
|
||||
// 聊天信息生成中……获取当前滚动条位置,判断是否需要滚动到底部
|
||||
const { run: generatingScroll } = useThrottleFn(
|
||||
() => {
|
||||
(force?: boolean) => {
|
||||
if (!ChatBoxRef.current) return;
|
||||
const isBottom =
|
||||
ChatBoxRef.current.scrollTop + ChatBoxRef.current.clientHeight + 150 >=
|
||||
ChatBoxRef.current.scrollHeight;
|
||||
|
||||
isBottom && scrollToBottom('auto');
|
||||
if (isBottom || force) {
|
||||
scrollToBottom('auto');
|
||||
}
|
||||
},
|
||||
{
|
||||
wait: 100
|
||||
@@ -321,7 +323,9 @@ const ChatBox = (
|
||||
return item;
|
||||
})
|
||||
);
|
||||
generatingScroll();
|
||||
|
||||
const forceScroll = event === SseResponseEventEnum.interactive;
|
||||
generatingScroll(forceScroll);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -529,7 +533,7 @@ const ChatBox = (
|
||||
});
|
||||
}
|
||||
|
||||
generatingScroll();
|
||||
generatingScroll(true);
|
||||
isPc && TextareaDom.current?.focus();
|
||||
}, 100);
|
||||
|
||||
|
@@ -180,21 +180,12 @@ const NodeCard = (props: Props) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
{!isFolded ? (
|
||||
<MyIcon
|
||||
name={'core/chat/chevronDown'}
|
||||
w={'24px'}
|
||||
h={'24px'}
|
||||
color={'myGray.500'}
|
||||
/>
|
||||
) : (
|
||||
<MyIcon
|
||||
name={'core/chat/chevronRight'}
|
||||
w={'24px'}
|
||||
h={'24px'}
|
||||
color={'myGray.500'}
|
||||
/>
|
||||
)}
|
||||
<MyIcon
|
||||
name={isFolded ? 'core/chat/chevronDown' : 'core/chat/chevronRight'}
|
||||
w={'24px'}
|
||||
h={'24px'}
|
||||
color={'myGray.500'}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
<Avatar src={avatar} borderRadius={'sm'} objectFit={'contain'} w={'30px'} h={'30px'} />
|
||||
|
@@ -22,6 +22,16 @@ export type StreamResponseType = {
|
||||
responseText: string;
|
||||
[DispatchNodeResponseKeyEnum.nodeResponse]: ChatHistoryItemResType[];
|
||||
};
|
||||
type ResponseQueueItemType =
|
||||
| { event: SseResponseEventEnum.fastAnswer | SseResponseEventEnum.answer; text: string }
|
||||
| { event: SseResponseEventEnum.interactive; [key: string]: any }
|
||||
| {
|
||||
event:
|
||||
| SseResponseEventEnum.toolCall
|
||||
| SseResponseEventEnum.toolParams
|
||||
| SseResponseEventEnum.toolResponse;
|
||||
[key: string]: any;
|
||||
};
|
||||
class FatalError extends Error {}
|
||||
|
||||
export const streamFetch = ({
|
||||
@@ -31,22 +41,14 @@ export const streamFetch = ({
|
||||
abortCtrl
|
||||
}: StreamFetchProps) =>
|
||||
new Promise<StreamResponseType>(async (resolve, reject) => {
|
||||
// First res
|
||||
const timeoutId = setTimeout(() => {
|
||||
abortCtrl.abort('Time out');
|
||||
}, 60000);
|
||||
|
||||
// response data
|
||||
let responseText = '';
|
||||
let responseQueue: (
|
||||
| { event: SseResponseEventEnum.fastAnswer | SseResponseEventEnum.answer; text: string }
|
||||
| {
|
||||
event:
|
||||
| SseResponseEventEnum.toolCall
|
||||
| SseResponseEventEnum.toolParams
|
||||
| SseResponseEventEnum.toolResponse;
|
||||
[key: string]: any;
|
||||
}
|
||||
)[] = [];
|
||||
let responseQueue: ResponseQueueItemType[] = [];
|
||||
let errMsg: string | undefined;
|
||||
let responseData: ChatHistoryItemResType[] = [];
|
||||
let finished = false;
|
||||
@@ -84,7 +86,7 @@ export const streamFetch = ({
|
||||
}
|
||||
|
||||
if (responseQueue.length > 0) {
|
||||
const fetchCount = Math.max(1, Math.round(responseQueue.length / 20));
|
||||
const fetchCount = Math.max(1, Math.round(responseQueue.length / 30));
|
||||
for (let i = 0; i < fetchCount; i++) {
|
||||
const item = responseQueue[i];
|
||||
onMessage(item);
|
||||
@@ -100,13 +102,20 @@ export const streamFetch = ({
|
||||
return finish();
|
||||
}
|
||||
|
||||
document.hidden
|
||||
? setTimeout(animateResponseText, 16)
|
||||
: requestAnimationFrame(animateResponseText);
|
||||
requestAnimationFrame(animateResponseText);
|
||||
}
|
||||
// start animation
|
||||
animateResponseText();
|
||||
|
||||
const pushDataToQueue = (data: ResponseQueueItemType) => {
|
||||
// If the document is hidden, the data is directly sent to the front end
|
||||
responseQueue.push(data);
|
||||
|
||||
if (document.hidden) {
|
||||
animateResponseText();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
// auto complete variables
|
||||
const variables = data?.variables || {};
|
||||
@@ -171,14 +180,14 @@ export const streamFetch = ({
|
||||
if (event === SseResponseEventEnum.answer) {
|
||||
const text = parseJson.choices?.[0]?.delta?.content || '';
|
||||
for (const item of text) {
|
||||
responseQueue.push({
|
||||
pushDataToQueue({
|
||||
event,
|
||||
text: item
|
||||
});
|
||||
}
|
||||
} else if (event === SseResponseEventEnum.fastAnswer) {
|
||||
const text = parseJson.choices?.[0]?.delta?.content || '';
|
||||
responseQueue.push({
|
||||
pushDataToQueue({
|
||||
event,
|
||||
text
|
||||
});
|
||||
@@ -187,7 +196,7 @@ export const streamFetch = ({
|
||||
event === SseResponseEventEnum.toolParams ||
|
||||
event === SseResponseEventEnum.toolResponse
|
||||
) {
|
||||
responseQueue.push({
|
||||
pushDataToQueue({
|
||||
event,
|
||||
...parseJson
|
||||
});
|
||||
@@ -204,7 +213,7 @@ export const streamFetch = ({
|
||||
variables: parseJson
|
||||
});
|
||||
} else if (event === SseResponseEventEnum.interactive) {
|
||||
responseQueue.push({
|
||||
pushDataToQueue({
|
||||
event,
|
||||
...parseJson
|
||||
});
|
||||
|
@@ -200,7 +200,7 @@ const ChatContextProvider = ({
|
||||
);
|
||||
} else {
|
||||
// Chat history not exists
|
||||
loadHistories();
|
||||
loadHistories(true);
|
||||
}
|
||||
},
|
||||
[histories, loadHistories, setHistories]
|
||||
|
Reference in New Issue
Block a user