mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
4.8.10 perf (#2630)
* perf: i18n init * i18n * fix: user select end status * fix: interactive workflow * fix: restart chat * fix: oauth login
This commit is contained in:
@@ -40,9 +40,17 @@ export const getLastInteractiveValue = (histories: ChatItemType[]) => {
|
||||
const lastValue = lastAIMessage.value[lastAIMessage.value.length - 1];
|
||||
|
||||
if (
|
||||
lastValue &&
|
||||
lastValue.type === ChatItemValueTypeEnum.interactive &&
|
||||
!!lastValue.interactive
|
||||
!lastValue ||
|
||||
lastValue.type !== ChatItemValueTypeEnum.interactive ||
|
||||
!lastValue.interactive
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check is user select
|
||||
if (
|
||||
lastValue.interactive.type === 'userSelect' &&
|
||||
!lastValue.interactive.params.userSelectedVal
|
||||
) {
|
||||
return lastValue.interactive;
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
|
||||
import { AIChatItemType } from '@fastgpt/global/core/chat/type';
|
||||
import { updateToolInputValue } from './utils';
|
||||
import { computedMaxToken, computedTemperature } from '../../../../ai/utils';
|
||||
import { sliceStrStartEnd } from '@fastgpt/global/common/string/tools';
|
||||
import { getNanoid, sliceStrStartEnd } from '@fastgpt/global/common/string/tools';
|
||||
import { addLog } from '../../../../../common/system/log';
|
||||
|
||||
type ToolRunResponseType = {
|
||||
@@ -367,6 +367,7 @@ async function streamResponse({
|
||||
});
|
||||
|
||||
let textAnswer = '';
|
||||
let callingTool: { name: string; arguments: string } | null = null;
|
||||
let toolCalls: ChatCompletionMessageToolCall[] = [];
|
||||
|
||||
for await (const part of stream) {
|
||||
@@ -390,69 +391,71 @@ async function streamResponse({
|
||||
});
|
||||
} else if (responseChoice?.tool_calls?.[0]) {
|
||||
const toolCall: ChatCompletionMessageToolCall = responseChoice.tool_calls[0];
|
||||
|
||||
// In a stream response, only one tool is returned at a time. If have id, description is executing a tool
|
||||
if (toolCall.id) {
|
||||
const toolNode = toolNodes.find((item) => item.nodeId === toolCall.function?.name);
|
||||
if (toolCall.id || callingTool) {
|
||||
// Start call tool
|
||||
if (toolCall.id) {
|
||||
callingTool = {
|
||||
name: toolCall.function.name || '',
|
||||
arguments: toolCall.function.arguments || ''
|
||||
};
|
||||
} else if (callingTool) {
|
||||
// Continue call
|
||||
callingTool.name += toolCall.function.name || '';
|
||||
callingTool.arguments += toolCall.function.arguments || '';
|
||||
}
|
||||
|
||||
const toolFunction = callingTool!;
|
||||
|
||||
const toolNode = toolNodes.find((item) => item.nodeId === toolFunction.name);
|
||||
|
||||
if (toolNode) {
|
||||
if (toolCall.function?.arguments === undefined) {
|
||||
toolCall.function.arguments = '';
|
||||
}
|
||||
// New tool, add to list.
|
||||
const toolId = getNanoid();
|
||||
toolCalls.push({
|
||||
...toolCall,
|
||||
id: toolId,
|
||||
function: toolFunction,
|
||||
toolName: toolNode.name,
|
||||
toolAvatar: toolNode.avatar
|
||||
});
|
||||
|
||||
// Get last tool call
|
||||
const lastToolCall = toolCalls[toolCalls.length - 1];
|
||||
|
||||
// new tool
|
||||
if (lastToolCall?.id !== toolCall.id) {
|
||||
toolCalls.push({
|
||||
...toolCall,
|
||||
toolName: toolNode.name,
|
||||
toolAvatar: toolNode.avatar
|
||||
});
|
||||
|
||||
workflowStreamResponse?.({
|
||||
event: SseResponseEventEnum.toolCall,
|
||||
data: {
|
||||
tool: {
|
||||
id: toolCall.id,
|
||||
toolName: toolNode.name,
|
||||
toolAvatar: toolNode.avatar,
|
||||
functionName: toolCall.function.name,
|
||||
params: toolCall.function.arguments,
|
||||
response: ''
|
||||
}
|
||||
workflowStreamResponse?.({
|
||||
event: SseResponseEventEnum.toolCall,
|
||||
data: {
|
||||
tool: {
|
||||
id: toolId,
|
||||
toolName: toolNode.name,
|
||||
toolAvatar: toolNode.avatar,
|
||||
functionName: toolFunction.name,
|
||||
params: toolFunction?.arguments ?? '',
|
||||
response: ''
|
||||
}
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
// last tool, update params
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* arg 插入最后一个工具的参数里 */
|
||||
const arg: string = toolCall?.function?.arguments ?? '';
|
||||
const currentTool = toolCalls[toolCalls.length - 1];
|
||||
|
||||
if (currentTool) {
|
||||
currentTool.function.arguments += arg;
|
||||
|
||||
workflowStreamResponse?.({
|
||||
write,
|
||||
event: SseResponseEventEnum.toolParams,
|
||||
data: {
|
||||
tool: {
|
||||
id: currentTool.id,
|
||||
toolName: '',
|
||||
toolAvatar: '',
|
||||
params: arg,
|
||||
response: ''
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
callingTool = null;
|
||||
}
|
||||
} else {
|
||||
/* arg 插入最后一个工具的参数里 */
|
||||
const arg: string = toolCall?.function?.arguments ?? '';
|
||||
const currentTool = toolCalls[toolCalls.length - 1];
|
||||
if (currentTool && arg) {
|
||||
currentTool.function.arguments += arg;
|
||||
|
||||
workflowStreamResponse?.({
|
||||
write,
|
||||
event: SseResponseEventEnum.toolParams,
|
||||
data: {
|
||||
tool: {
|
||||
id: currentTool.id,
|
||||
toolName: '',
|
||||
toolAvatar: '',
|
||||
params: arg,
|
||||
response: ''
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -137,6 +137,13 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
||||
let chatNodeUsages: ChatNodeUsageType[] = [];
|
||||
let toolRunResponse: ToolRunResponseItemType;
|
||||
let debugNextStepRunNodes: RuntimeNodeItemType[] = [];
|
||||
// 记录交互节点,交互节点需要在工作流完全结束后再进行计算
|
||||
let workflowInteractiveResponse:
|
||||
| {
|
||||
entryNodeIds: string[];
|
||||
interactiveResponse: UserSelectInteractive;
|
||||
}
|
||||
| undefined;
|
||||
|
||||
/* Store special response field */
|
||||
function pushStore(
|
||||
@@ -338,6 +345,16 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
||||
|
||||
if (!nodeRunResult) return [];
|
||||
|
||||
// In the current version, only one interactive node is allowed at the same time
|
||||
const interactiveResponse = nodeRunResult.result?.[DispatchNodeResponseKeyEnum.interactive];
|
||||
if (interactiveResponse) {
|
||||
workflowInteractiveResponse = {
|
||||
entryNodeIds: [nodeRunResult.node.nodeId],
|
||||
interactiveResponse
|
||||
};
|
||||
return [];
|
||||
}
|
||||
|
||||
// Update the node output at the end of the run and get the next nodes
|
||||
let { nextStepActiveNodes, nextStepSkipNodes } = nodeOutput(
|
||||
nodeRunResult.node,
|
||||
@@ -351,18 +368,6 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
||||
(node, index, self) => self.findIndex((t) => t.nodeId === node.nodeId) === index
|
||||
);
|
||||
|
||||
// In the current version, only one interactive node is allowed at the same time
|
||||
const interactiveResponse = nodeRunResult.result?.[DispatchNodeResponseKeyEnum.interactive];
|
||||
if (interactiveResponse) {
|
||||
chatAssistantResponse.push(
|
||||
handleInteractiveResult({
|
||||
entryNodeIds: [nodeRunResult.node.nodeId],
|
||||
interactiveResponse
|
||||
})
|
||||
);
|
||||
return [];
|
||||
}
|
||||
|
||||
// Run next nodes(先运行 run 的,再运行 skip 的)
|
||||
const nextStepActiveNodesResults = (
|
||||
await Promise.all(nextStepActiveNodes.map((node) => checkNodeCanRun(node)))
|
||||
@@ -543,6 +548,15 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
||||
await nodeRunWithActive(pluginOutputModule);
|
||||
}
|
||||
|
||||
// Interactive node
|
||||
if (workflowInteractiveResponse) {
|
||||
const interactiveResult = handleInteractiveResult({
|
||||
entryNodeIds: workflowInteractiveResponse.entryNodeIds,
|
||||
interactiveResponse: workflowInteractiveResponse.interactiveResponse
|
||||
});
|
||||
chatAssistantResponse.push(interactiveResult);
|
||||
}
|
||||
|
||||
return {
|
||||
flowResponses: chatResponses,
|
||||
flowUsages: chatNodeUsages,
|
||||
|
@@ -715,11 +715,13 @@ export const theme = extendTheme({
|
||||
lg: '1px solid #D0E0E2'
|
||||
},
|
||||
radii: {
|
||||
xs: '4px',
|
||||
sm: '6px',
|
||||
md: '8px',
|
||||
lg: '12px',
|
||||
xl: '16px'
|
||||
none: '0',
|
||||
xs: '0.25rem',
|
||||
sm: '0.375rem',
|
||||
md: '0.5rem',
|
||||
semilg: '0.625rem',
|
||||
lg: '0.75rem',
|
||||
xl: '1rem'
|
||||
},
|
||||
shadows: {
|
||||
1: '0px 1px 2px 0px rgba(19, 51, 107, 0.05), 0px 0px 1px 0px rgba(19, 51, 107, 0.08)',
|
||||
|
Reference in New Issue
Block a user