mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-24 13:53:50 +00:00
@@ -84,24 +84,25 @@ weight: 813
|
|||||||
|
|
||||||
## V4.8.11 更新说明
|
## V4.8.11 更新说明
|
||||||
|
|
||||||
1.
|
1. 新增 - 表单输入节点,允许用户在工作流中让用户输入一些信息。
|
||||||
2. 新增 - 循环运行节点,可传入数组进行批量调用,目前最多支持 50 长度的数组串行执行。
|
2. 新增 - 循环运行节点,可传入数组进行批量调用,目前最多支持 50 长度的数组串行执行。
|
||||||
3. 新增 - 聊天记录滚动加载,不再只加载 30 条。
|
3. 新增 - 节点支持折叠。
|
||||||
4. 新增 - 工作流增加触摸板优先模式。
|
4. 新增 - 聊天记录滚动加载,不再只加载 30 条。
|
||||||
5. 新增 - 沙盒增加字符串转 base64 全局方法。
|
5. 新增 - 工作流增加触摸板优先模式,可以通过工作流右下角按键进行切换。
|
||||||
6. 新增 - 支持 Openai o1 模型,需增加模型的 `defaultConfig` 配置,覆盖 `temperature`、`max_tokens` 和 `stream`配置,o1 不支持 stream 模式, 详细可重新拉取 `config.json` 配置文件查看。
|
6. 新增 - 沙盒增加字符串转 base64 全局方法(全局变量 strToBase64)。
|
||||||
7. 新增 - AI 对话节点知识库引用,支持配置 role=system 和 role=user,已配置的过自定义提示词的节点将会保持 user 模式,其余用户将转成 system 模式。
|
7. 新增 - 支持 Openai o1 模型,需增加模型的 `defaultConfig` 配置,覆盖 `temperature`、`max_tokens` 和 `stream`配置,o1 不支持 stream 模式, 详细可重新拉取 `config.json` 配置文件查看。
|
||||||
8. 新增 - 插件支持上传系统文件。
|
8. 新增 - AI 对话节点知识库引用,支持配置 role=system 和 role=user,已配置的过自定义提示词的节点将会保持 user 模式,其余用户将转成 system 模式。
|
||||||
9. 新增 - 插件输出,支持指定字段作为工具响应。
|
9. 新增 - 插件支持上传系统文件。
|
||||||
10. 新增 - 支持工作流嵌套子应用时,可以设置`非流模式`,同时简易模式也可以选择工作流作为插件了,简易模式调用子应用时,都将强制使用非流模式。
|
10. 新增 - 插件输出,支持指定字段作为工具响应。
|
||||||
11. 新增 - 调试模式下,子应用调用,支持返回详细运行数据。
|
11. 新增 - 支持工作流嵌套子应用时,可以设置`非流模式`,同时简易模式也可以选择工作流作为插件了,简易模式调用子应用时,都将强制使用非流模式。
|
||||||
12. 新增 - 保留所有模式下子应用嵌套调用的日志。
|
12. 新增 - 调试模式下,子应用调用,支持返回详细运行数据。
|
||||||
13. 优化 - 工作流嵌套层级限制 20 层,避免因编排不合理导致的无限死循环。
|
13. 新增 - 保留所有模式下子应用嵌套调用的日志。
|
||||||
14. 优化 - 工作流 handler 性能优化。
|
14. 优化 - 工作流嵌套层级限制 20 层,避免因编排不合理导致的无限死循环。
|
||||||
15. 优化 - 工作流快捷键,避免调试测试时也会触发。
|
15. 优化 - 工作流 handler 性能优化。
|
||||||
16. 优化 - 流输出,切换 tab 时仍可以继续输出。
|
16. 优化 - 工作流快捷键,避免调试测试时也会触发复制和回退。
|
||||||
17. 优化 - 完善外部文件知识库相关 API
|
17. 优化 - 流输出,切换浏览器 Tab 后仍可以继续输出。
|
||||||
18. 修复 - 知识库选择权限问题。
|
18. 优化 - 完善外部文件知识库相关 API
|
||||||
19. 修复 - 空 chatId 发起对话,首轮携带用户选择时会异常。
|
19. 修复 - 知识库选择权限问题。
|
||||||
20. 修复 - createDataset 接口,intro 为赋值。
|
20. 修复 - 空 chatId 发起对话,首轮携带用户选择时会异常。
|
||||||
21. 修复 - 对话框渲染性能问题。
|
21. 修复 - createDataset 接口,intro 为赋值。
|
||||||
|
22. 修复 - 对话框渲染性能问题。
|
||||||
|
@@ -20,6 +20,9 @@ type FormInputResponse = DispatchNodeResultType<{
|
|||||||
[NodeOutputKeyEnum.formInputResult]?: Record<string, any>;
|
[NodeOutputKeyEnum.formInputResult]?: Record<string, any>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
/*
|
||||||
|
用户输入都内容,将会以 JSON 字符串格式进入工作流,可以从 query 的 text 中获取。
|
||||||
|
*/
|
||||||
export const dispatchFormInput = async (props: Props): Promise<FormInputResponse> => {
|
export const dispatchFormInput = async (props: Props): Promise<FormInputResponse> => {
|
||||||
const {
|
const {
|
||||||
histories,
|
histories,
|
||||||
|
@@ -199,13 +199,15 @@ const ChatBox = (
|
|||||||
|
|
||||||
// 聊天信息生成中……获取当前滚动条位置,判断是否需要滚动到底部
|
// 聊天信息生成中……获取当前滚动条位置,判断是否需要滚动到底部
|
||||||
const { run: generatingScroll } = useThrottleFn(
|
const { run: generatingScroll } = useThrottleFn(
|
||||||
() => {
|
(force?: boolean) => {
|
||||||
if (!ChatBoxRef.current) return;
|
if (!ChatBoxRef.current) return;
|
||||||
const isBottom =
|
const isBottom =
|
||||||
ChatBoxRef.current.scrollTop + ChatBoxRef.current.clientHeight + 150 >=
|
ChatBoxRef.current.scrollTop + ChatBoxRef.current.clientHeight + 150 >=
|
||||||
ChatBoxRef.current.scrollHeight;
|
ChatBoxRef.current.scrollHeight;
|
||||||
|
|
||||||
isBottom && scrollToBottom('auto');
|
if (isBottom || force) {
|
||||||
|
scrollToBottom('auto');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
wait: 100
|
wait: 100
|
||||||
@@ -321,7 +323,9 @@ const ChatBox = (
|
|||||||
return item;
|
return item;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
generatingScroll();
|
|
||||||
|
const forceScroll = event === SseResponseEventEnum.interactive;
|
||||||
|
generatingScroll(forceScroll);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -529,7 +533,7 @@ const ChatBox = (
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
generatingScroll();
|
generatingScroll(true);
|
||||||
isPc && TextareaDom.current?.focus();
|
isPc && TextareaDom.current?.focus();
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
|
@@ -180,21 +180,12 @@ const NodeCard = (props: Props) => {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!isFolded ? (
|
<MyIcon
|
||||||
<MyIcon
|
name={isFolded ? 'core/chat/chevronDown' : 'core/chat/chevronRight'}
|
||||||
name={'core/chat/chevronDown'}
|
w={'24px'}
|
||||||
w={'24px'}
|
h={'24px'}
|
||||||
h={'24px'}
|
color={'myGray.500'}
|
||||||
color={'myGray.500'}
|
/>
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<MyIcon
|
|
||||||
name={'core/chat/chevronRight'}
|
|
||||||
w={'24px'}
|
|
||||||
h={'24px'}
|
|
||||||
color={'myGray.500'}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
<Avatar src={avatar} borderRadius={'sm'} objectFit={'contain'} w={'30px'} h={'30px'} />
|
<Avatar src={avatar} borderRadius={'sm'} objectFit={'contain'} w={'30px'} h={'30px'} />
|
||||||
|
@@ -22,6 +22,16 @@ export type StreamResponseType = {
|
|||||||
responseText: string;
|
responseText: string;
|
||||||
[DispatchNodeResponseKeyEnum.nodeResponse]: ChatHistoryItemResType[];
|
[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 {}
|
class FatalError extends Error {}
|
||||||
|
|
||||||
export const streamFetch = ({
|
export const streamFetch = ({
|
||||||
@@ -31,22 +41,14 @@ export const streamFetch = ({
|
|||||||
abortCtrl
|
abortCtrl
|
||||||
}: StreamFetchProps) =>
|
}: StreamFetchProps) =>
|
||||||
new Promise<StreamResponseType>(async (resolve, reject) => {
|
new Promise<StreamResponseType>(async (resolve, reject) => {
|
||||||
|
// First res
|
||||||
const timeoutId = setTimeout(() => {
|
const timeoutId = setTimeout(() => {
|
||||||
abortCtrl.abort('Time out');
|
abortCtrl.abort('Time out');
|
||||||
}, 60000);
|
}, 60000);
|
||||||
|
|
||||||
// response data
|
// response data
|
||||||
let responseText = '';
|
let responseText = '';
|
||||||
let responseQueue: (
|
let responseQueue: ResponseQueueItemType[] = [];
|
||||||
| { event: SseResponseEventEnum.fastAnswer | SseResponseEventEnum.answer; text: string }
|
|
||||||
| {
|
|
||||||
event:
|
|
||||||
| SseResponseEventEnum.toolCall
|
|
||||||
| SseResponseEventEnum.toolParams
|
|
||||||
| SseResponseEventEnum.toolResponse;
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
)[] = [];
|
|
||||||
let errMsg: string | undefined;
|
let errMsg: string | undefined;
|
||||||
let responseData: ChatHistoryItemResType[] = [];
|
let responseData: ChatHistoryItemResType[] = [];
|
||||||
let finished = false;
|
let finished = false;
|
||||||
@@ -84,7 +86,7 @@ export const streamFetch = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (responseQueue.length > 0) {
|
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++) {
|
for (let i = 0; i < fetchCount; i++) {
|
||||||
const item = responseQueue[i];
|
const item = responseQueue[i];
|
||||||
onMessage(item);
|
onMessage(item);
|
||||||
@@ -100,13 +102,20 @@ export const streamFetch = ({
|
|||||||
return finish();
|
return finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
document.hidden
|
requestAnimationFrame(animateResponseText);
|
||||||
? setTimeout(animateResponseText, 16)
|
|
||||||
: requestAnimationFrame(animateResponseText);
|
|
||||||
}
|
}
|
||||||
// start animation
|
// start animation
|
||||||
animateResponseText();
|
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 {
|
try {
|
||||||
// auto complete variables
|
// auto complete variables
|
||||||
const variables = data?.variables || {};
|
const variables = data?.variables || {};
|
||||||
@@ -171,14 +180,14 @@ export const streamFetch = ({
|
|||||||
if (event === SseResponseEventEnum.answer) {
|
if (event === SseResponseEventEnum.answer) {
|
||||||
const text = parseJson.choices?.[0]?.delta?.content || '';
|
const text = parseJson.choices?.[0]?.delta?.content || '';
|
||||||
for (const item of text) {
|
for (const item of text) {
|
||||||
responseQueue.push({
|
pushDataToQueue({
|
||||||
event,
|
event,
|
||||||
text: item
|
text: item
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (event === SseResponseEventEnum.fastAnswer) {
|
} else if (event === SseResponseEventEnum.fastAnswer) {
|
||||||
const text = parseJson.choices?.[0]?.delta?.content || '';
|
const text = parseJson.choices?.[0]?.delta?.content || '';
|
||||||
responseQueue.push({
|
pushDataToQueue({
|
||||||
event,
|
event,
|
||||||
text
|
text
|
||||||
});
|
});
|
||||||
@@ -187,7 +196,7 @@ export const streamFetch = ({
|
|||||||
event === SseResponseEventEnum.toolParams ||
|
event === SseResponseEventEnum.toolParams ||
|
||||||
event === SseResponseEventEnum.toolResponse
|
event === SseResponseEventEnum.toolResponse
|
||||||
) {
|
) {
|
||||||
responseQueue.push({
|
pushDataToQueue({
|
||||||
event,
|
event,
|
||||||
...parseJson
|
...parseJson
|
||||||
});
|
});
|
||||||
@@ -204,7 +213,7 @@ export const streamFetch = ({
|
|||||||
variables: parseJson
|
variables: parseJson
|
||||||
});
|
});
|
||||||
} else if (event === SseResponseEventEnum.interactive) {
|
} else if (event === SseResponseEventEnum.interactive) {
|
||||||
responseQueue.push({
|
pushDataToQueue({
|
||||||
event,
|
event,
|
||||||
...parseJson
|
...parseJson
|
||||||
});
|
});
|
||||||
|
@@ -200,7 +200,7 @@ const ChatContextProvider = ({
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Chat history not exists
|
// Chat history not exists
|
||||||
loadHistories();
|
loadHistories(true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[histories, loadHistories, setHistories]
|
[histories, loadHistories, setHistories]
|
||||||
|
Reference in New Issue
Block a user