Skip to content

Commit

Permalink
4.8.11 perf (#2832)
Browse files Browse the repository at this point in the history
* save toast

* perf: surya ocr

* perf: remove same model name

* fix: indexes

* perf: ip check

* feat: Fixed the version number of the subapplication

* feat: simple app get latest child version

* perf: update child dispatch variables

* feat: variables update doc
  • Loading branch information
c121914yu authored Sep 28, 2024
1 parent f7a8203 commit f2749cb
Show file tree
Hide file tree
Showing 34 changed files with 398 additions and 268 deletions.
30 changes: 16 additions & 14 deletions docSite/content/zh-cn/docs/development/upgrading/4811.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,19 @@ weight: 813
7. 新增 - 支持 Openai o1 模型,需增加模型的 `defaultConfig` 配置,覆盖 `temperature``max_tokens``stream`配置,o1 不支持 stream 模式, 详细可重新拉取 `config.json` 配置文件查看。
8. 新增 - AI 对话节点知识库引用,支持配置 role=system 和 role=user,已配置的过自定义提示词的节点将会保持 user 模式,其余用户将转成 system 模式。
9. 新增 - 插件支持上传系统文件。
10. 新增 - 插件输出,支持指定字段作为工具响应。
11. 新增 - 支持工作流嵌套子应用时,可以设置`非流模式`,同时简易模式也可以选择工作流作为插件了,简易模式调用子应用时,都将强制使用非流模式。
12. 新增 - 调试模式下,子应用调用,支持返回详细运行数据。
13. 新增 - 保留所有模式下子应用嵌套调用的日志。
14. 优化 - 工作流嵌套层级限制 20 层,避免因编排不合理导致的无限死循环。
15. 优化 - 工作流 handler 性能优化。
16. 优化 - 工作流快捷键,避免调试测试时也会触发复制和回退。
17. 优化 - 流输出,切换浏览器 Tab 后仍可以继续输出。
18. 优化 - 完善外部文件知识库相关 API
19. 修复 - 知识库选择权限问题。
20. 修复 - 空 chatId 发起对话,首轮携带用户选择时会异常。
21. 修复 - createDataset 接口,intro 为赋值。
22. 修复 - 对话框渲染性能问题。
23. 修复 - 工具调用历史记录存储不正确。
10. 新增 - 子应用嵌套调用时,版本锁定。主应用未主动更新版本时,不会取最新版进行执行,保证主应用服务稳定。
11. 新增 - 插件输出,支持指定字段作为工具响应。
12. 新增 - 支持工作流嵌套子应用时,可以设置`非流模式`,同时简易模式也可以选择工作流作为插件了,简易模式调用子应用时,都将强制使用非流模式。
13. 新增 - 调试模式下,子应用调用,支持返回详细运行数据。
14. 新增 - 保留所有模式下子应用嵌套调用的日志。
15. 优化 - 工作流嵌套层级限制 20 层,避免因编排不合理导致的无限死循环。
16. 优化 - 工作流 handler 性能优化。
17. 优化 - 工作流快捷键,避免调试测试时也会触发复制和回退。
18. 修复 - 工作流工具调用中修改全局变量后,无法传递到后续流程。
19. 优化 - 流输出,切换浏览器 Tab 后仍可以继续输出。
20. 优化 - 完善外部文件知识库相关 API
21. 修复 - 知识库选择权限问题。
22. 修复 - 空 chatId 发起对话,首轮携带用户选择时会异常。
23. 修复 - createDataset 接口,intro 为赋值。
24. 修复 - 对话框渲染性能问题。
25. 修复 - 工具调用历史记录存储不正确。
1 change: 1 addition & 0 deletions packages/global/core/workflow/runtime/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export type RuntimeNodeItemType = {
outputs: FlowNodeOutputItemType[];

pluginId?: string; // workflow id / plugin id
version: string;
};

export type PluginRuntimeType = {
Expand Down
3 changes: 2 additions & 1 deletion packages/global/core/workflow/runtime/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ export const storeNodes2RuntimeNodes = (
isEntry: entryNodeIds.includes(node.nodeId),
inputs: node.inputs,
outputs: node.outputs,
pluginId: node.pluginId
pluginId: node.pluginId,
version: node.version
};
}) || []
);
Expand Down
1 change: 1 addition & 0 deletions packages/service/core/ai/rerank/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export function reRankRecall({
}));
})
.catch((err) => {
console.log(err);
addLog.error('rerank error', err);

return [];
Expand Down
25 changes: 0 additions & 25 deletions packages/service/core/app/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { AppSchema } from '@fastgpt/global/core/app/type';
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { getLLMModel } from '../ai/model';
import { MongoAppVersion } from './version/schema';
import { MongoApp } from './schema';

export const beforeUpdateAppFormat = <T extends AppSchema['modules'] | undefined>({
Expand Down Expand Up @@ -46,30 +45,6 @@ export const beforeUpdateAppFormat = <T extends AppSchema['modules'] | undefined
};
};

export const getAppLatestVersion = async (appId: string, app?: AppSchema) => {
const version = await MongoAppVersion.findOne({
appId,
isPublish: true
})
.sort({
time: -1
})
.lean();

if (version) {
return {
nodes: version.nodes,
edges: version.edges,
chatConfig: version.chatConfig || app?.chatConfig || {}
};
}
return {
nodes: app?.modules || [],
edges: app?.edges || [],
chatConfig: app?.chatConfig || {}
};
};

/* Get apps */
export async function findAppAndAllChildren({
teamId,
Expand Down
121 changes: 86 additions & 35 deletions packages/service/core/app/plugin/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { cloneDeep } from 'lodash';
import { MongoApp } from '../schema';
import { SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type';
import { getSystemPluginTemplates } from '../../../../plugins/register';
import { getAppLatestVersion, getAppVersionById } from '../version/controller';

/*
plugin id rule:
Expand All @@ -34,38 +35,14 @@ export async function splitCombinePluginId(id: string) {
return { source, pluginId: id };
}

const getChildAppTemplateById = async (
id: string
): Promise<SystemPluginTemplateItemType & { teamId?: string }> => {
const { source, pluginId } = await splitCombinePluginId(id);
type ChildAppType = SystemPluginTemplateItemType & { teamId?: string };
const getSystemPluginTemplateById = async (
pluginId: string
): Promise<SystemPluginTemplateItemType> => {
const item = getSystemPluginTemplates().find((plugin) => plugin.id === pluginId);
if (!item) return Promise.reject('plugin not found');

if (source === PluginSourceEnum.personal) {
const item = await MongoApp.findById(id).lean();
if (!item) return Promise.reject('plugin not found');

return {
id: String(item._id),
teamId: String(item.teamId),
name: item.name,
avatar: item.avatar,
intro: item.intro,
showStatus: true,
workflow: {
nodes: item.modules,
edges: item.edges,
chatConfig: item.chatConfig
},
templateType: FlowNodeTemplateTypeEnum.teamApp,
version: item?.pluginData?.nodeVersion || defaultNodeVersion,
originCost: 0,
currentCost: 0
};
} else {
const item = getSystemPluginTemplates().find((plugin) => plugin.id === pluginId);
if (!item) return Promise.reject('plugin not found');

return cloneDeep(item);
}
return cloneDeep(item);
};

/* format plugin modules to plugin preview module */
Expand All @@ -74,7 +51,39 @@ export async function getChildAppPreviewNode({
}: {
id: string;
}): Promise<FlowNodeTemplateType> {
const app = await getChildAppTemplateById(id);
const app: ChildAppType = await (async () => {
const { source, pluginId } = await splitCombinePluginId(id);

if (source === PluginSourceEnum.personal) {
const item = await MongoApp.findById(id).lean();
if (!item) return Promise.reject('plugin not found');

const version = await getAppLatestVersion(id, item);

if (!version.versionId) return Promise.reject('App version not found');

return {
id: String(item._id),
teamId: String(item.teamId),
name: item.name,
avatar: item.avatar,
intro: item.intro,
showStatus: true,
workflow: {
nodes: version.nodes,
edges: version.edges,
chatConfig: version.chatConfig
},
templateType: FlowNodeTemplateTypeEnum.teamApp,
version: version.versionId,
originCost: 0,
currentCost: 0
};
} else {
return getSystemPluginTemplateById(pluginId);
}
})();

const isPlugin = !!app.workflow.nodes.find(
(node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput
);
Expand All @@ -99,9 +108,51 @@ export async function getChildAppPreviewNode({
};
}

/* run plugin time */
export async function getChildAppRuntimeById(id: string): Promise<PluginRuntimeType> {
const app = await getChildAppTemplateById(id);
/*
Get runtime plugin data
System plugin: plugin id
Personal plugin: Version id
*/
export async function getChildAppRuntimeById(
id: string,
versionId?: string
): Promise<PluginRuntimeType> {
const app: ChildAppType = await (async () => {
const { source, pluginId } = await splitCombinePluginId(id);

if (source === PluginSourceEnum.personal) {
const item = await MongoApp.findById(id).lean();
if (!item) return Promise.reject('plugin not found');

const version = await getAppVersionById({
appId: id,
versionId,
app: item
});

return {
id: String(item._id),
teamId: String(item.teamId),
name: item.name,
avatar: item.avatar,
intro: item.intro,
showStatus: true,
workflow: {
nodes: version.nodes,
edges: version.edges,
chatConfig: version.chatConfig
},
templateType: FlowNodeTemplateTypeEnum.teamApp,

// 用不到
version: item?.pluginData?.nodeVersion || defaultNodeVersion,
originCost: 0,
currentCost: 0
};
} else {
return getSystemPluginTemplateById(pluginId);
}
})();

return {
id: app.id,
Expand Down
59 changes: 59 additions & 0 deletions packages/service/core/app/version/controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { AppSchema } from '@fastgpt/global/core/app/type';
import { MongoAppVersion } from './schema';
import { Types } from '../../../common/mongo';

export const getAppLatestVersion = async (appId: string, app?: AppSchema) => {
const version = await MongoAppVersion.findOne({
appId,
isPublish: true
})
.sort({
time: -1
})
.lean();

if (version) {
return {
versionId: version._id,
nodes: version.nodes,
edges: version.edges,
chatConfig: version.chatConfig || app?.chatConfig || {}
};
}
return {
versionId: app?.pluginData?.nodeVersion,
nodes: app?.modules || [],
edges: app?.edges || [],
chatConfig: app?.chatConfig || {}
};
};

export const getAppVersionById = async ({
appId,
versionId,
app
}: {
appId: string;
versionId?: string;
app?: AppSchema;
}) => {
// 检查 versionId 是否符合 ObjectId 格式
if (versionId && Types.ObjectId.isValid(versionId)) {
const version = await MongoAppVersion.findOne({
_id: versionId,
appId
}).lean();

if (version) {
return {
versionId: version._id,
nodes: version.nodes,
edges: version.edges,
chatConfig: version.chatConfig || app?.chatConfig || {}
};
}
}

// If the version does not exist, the latest version is returned
return getAppLatestVersion(appId, app);
};
14 changes: 12 additions & 2 deletions packages/service/core/workflow/dispatch/agent/runTool/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,18 @@ export const dispatchRunTools = async (props: DispatchToolModuleProps): Promise<
});

// flat child tool response
const childToolResponse = dispatchFlowResponse.map((item) => item.flowResponses).flat();
const newVariables = dispatchFlowResponse[dispatchFlowResponse.length - 1]?.newVariables;
let newVariables: Record<string, any> = props.variables;
const childToolResponse = dispatchFlowResponse
.map((item) => {
// Computed new variables
newVariables = {
...newVariables,
...item.newVariables
};

return item.flowResponses;
})
.flat();

// concat tool usage
const totalPointsUsage =
Expand Down
2 changes: 1 addition & 1 deletion packages/service/core/workflow/dispatch/loop/runLoop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const dispatchLoop = async (props: Props): Promise<Response> => {
const loopDetail: ChatHistoryItemResType[] = [];
let assistantResponses: AIChatItemValueItemType[] = [];
let totalPoints = 0;
let newVariables: Record<string, any> = {};
let newVariables: Record<string, any> = props.variables;

for await (const item of loopInputArray) {
const response = await dispatchWorkFlow({
Expand Down
4 changes: 2 additions & 2 deletions packages/service/core/workflow/dispatch/plugin/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type RunPluginResponse = DispatchNodeResultType<{}>;

export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPluginResponse> => {
const {
node: { pluginId },
node: { pluginId, version },
runningAppInfo,
query,
params: { system_forbid_stream = false, ...data } // Plugin input
Expand All @@ -45,7 +45,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
per: ReadPermissionVal
});

const plugin = await getChildAppRuntimeById(pluginId);
const plugin = await getChildAppRuntimeById(pluginId, version);

const outputFilterMap =
plugin.nodes
Expand Down
Loading

0 comments on commit f2749cb

Please sign in to comment.