Skip to content

Commit

Permalink
4.8.10 perf (labring#2630)
Browse files Browse the repository at this point in the history
* perf: i18n init

* i18n

* fix: user select end status

* fix: interactive workflow

* fix: restart chat

* fix: oauth login
  • Loading branch information
c121914yu authored and FinleyGe committed Sep 10, 2024
1 parent 11daabd commit c8bc091
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 132 deletions.
14 changes: 11 additions & 3 deletions packages/global/core/workflow/runtime/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
115 changes: 59 additions & 56 deletions packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
});
callingTool = null;
}
}

/* arg 插入最后一个工具的参数里 */
const arg: string = toolCall?.function?.arguments ?? '';
const currentTool = toolCalls[toolCalls.length - 1];

if (currentTool) {
currentTool.function.arguments += arg;
} 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: ''
workflowStreamResponse?.({
write,
event: SseResponseEventEnum.toolParams,
data: {
tool: {
id: currentTool.id,
toolName: '',
toolAvatar: '',
params: arg,
response: ''
}
}
}
});
});
}
}
}
}
Expand Down
38 changes: 26 additions & 12 deletions packages/service/core/workflow/dispatch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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,
Expand All @@ -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)))
Expand Down Expand Up @@ -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,
Expand Down
12 changes: 7 additions & 5 deletions packages/web/styles/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)',
Expand Down
12 changes: 6 additions & 6 deletions projects/app/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# --------- install dependence -----------
FROM node:20.14.0-alpine AS mainDeps
FROM node:20.14.0-alpine AS maindeps
WORKDIR /app

ARG proxy
Expand All @@ -26,10 +26,10 @@ ARG proxy

# copy common node_modules and one project node_modules
COPY package.json pnpm-workspace.yaml .npmrc tsconfig.json ./
COPY --from=mainDeps /app/node_modules ./node_modules
COPY --from=mainDeps /app/packages ./packages
COPY --from=maindeps /app/node_modules ./node_modules
COPY --from=maindeps /app/packages ./packages
COPY ./projects/app ./projects/app
COPY --from=mainDeps /app/projects/app/node_modules ./projects/app/node_modules
COPY --from=maindeps /app/projects/app/node_modules ./projects/app/node_modules

RUN [ -z "$proxy" ] || sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories

Expand Down Expand Up @@ -63,9 +63,9 @@ COPY --from=builder --chown=nextjs:nodejs /app/projects/app/.next/server/chunks
COPY --from=builder --chown=nextjs:nodejs /app/projects/app/.next/server/worker /app/projects/app/.next/server/worker

# copy standload packages
COPY --from=mainDeps /app/node_modules/tiktoken ./node_modules/tiktoken
COPY --from=maindeps /app/node_modules/tiktoken ./node_modules/tiktoken
RUN rm -rf ./node_modules/tiktoken/encoders
COPY --from=mainDeps /app/node_modules/@zilliz/milvus2-sdk-node ./node_modules/@zilliz/milvus2-sdk-node
COPY --from=maindeps /app/node_modules/@zilliz/milvus2-sdk-node ./node_modules/@zilliz/milvus2-sdk-node


# copy package.json to version file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ import ChatBoxDivider from '../../Divider';
import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat';
import { getNanoid } from '@fastgpt/global/common/string/tools';
import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
import { checkIsInteractiveByHistories, formatChatValue2InputType } from './utils';
import {
checkIsInteractiveByHistories,
formatChatValue2InputType,
setUserSelectResultToHistories
} from './utils';
import { textareaMinH } from './constants';
import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import ChatProvider, { ChatBoxContext, ChatProviderProps } from './Provider';
Expand Down Expand Up @@ -93,14 +97,6 @@ type Props = OutLinkChatAuthProps &
onDelMessage?: (e: { contentId: string }) => void;
};

/*
The input is divided into sections
1. text
2. img
3. file
4. ....
*/

const ChatBox = (
{
feedbackType = FeedbackTypeEnum.hidden,
Expand Down Expand Up @@ -377,7 +373,13 @@ const ChatBox = (
* user confirm send prompt
*/
const sendPrompt: SendPromptFnType = useCallback(
({ text = '', files = [], history = chatHistories, autoTTSResponse = false }) => {
({
text = '',
files = [],
history = chatHistories,
autoTTSResponse = false,
isInteractivePrompt = false
}) => {
variablesForm.handleSubmit(
async (variables) => {
if (!onStartChat) return;
Expand Down Expand Up @@ -444,6 +446,7 @@ const ChatBox = (
] as UserChatItemValueItemType[],
status: 'finish'
},
// 普通 chat 模式,需要增加一个 AI 来接收响应消息
{
dataId: responseChatId,
obj: ChatRoleEnum.AI,
Expand All @@ -459,28 +462,34 @@ const ChatBox = (
}
];

const isInteractive = checkIsInteractiveByHistories(history);
// Update histories(Interactive input does not require new session rounds)
setChatHistories(isInteractive ? newChatList.slice(0, -2) : newChatList);
setChatHistories(
isInteractivePrompt
? // 把交互的结果存储到对话记录中,交互模式下,不需要新的会话轮次
setUserSelectResultToHistories(newChatList.slice(0, -2), text)
: newChatList
);

// 清空输入内容
resetInputVal({});
setQuestionGuide([]);
scrollToBottom('smooth', 100);

try {
// create abort obj
const abortSignal = new AbortController();
chatController.current = abortSignal;

// Last empty ai message will be removed
// 最后一条 AI 消息是空的,会被过滤掉,这里得到的 messages,不会包含最后一条 AI 消息,所以不需要 slice 了。
// 这里,无论是否为交互模式,最后都是 Human 的消息。
const messages = chats2GPTMessages({ messages: newChatList, reserveId: true });

const {
responseData,
responseText,
isNewChat = false
} = await onStartChat({
messages: messages,
messages, // 保证最后一条是 Human 的消息
responseChatItemId: responseChatId,
controller: abortSignal,
generatingMessage: (e) => generatingMessage({ ...e, autoTTSResponse }),
Expand Down Expand Up @@ -847,12 +856,6 @@ const ChatBox = (
abortRequest();
setValue('chatStarted', false);
scrollToBottom('smooth', 500);
},
scrollToBottom,
sendPrompt: (question: string) => {
sendPrompt({
text: question
});
}
}));

Expand Down
Loading

0 comments on commit c8bc091

Please sign in to comment.