Skip to content

Commit

Permalink
feat: admin add custom plugin (#2582)
Browse files Browse the repository at this point in the history
* feat: admin add custom plugin

* refresh plugins

* plugin input box ui

* fix: run plugin varialbes error

* perf: comment

* fix: ts
  • Loading branch information
c121914yu authored Aug 30, 2024
1 parent 9d5fd24 commit 060492d
Show file tree
Hide file tree
Showing 18 changed files with 127 additions and 84 deletions.
55 changes: 28 additions & 27 deletions docSite/content/zh-cn/docs/development/upgrading/4810.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,30 +54,31 @@ curl --location --request POST 'https://{{host}}/api/admin/initv4810' \
5. 新增 - 工作流本次编辑记录,取代自动保存
6. 新增 - 工作流版本支持重命名
7. 新增 - 应用调用迁移成单独节点,同时可以传递全局变量和用户的文件。
8. 商业版新增 - 飞书机器人接入
9. 商业版新增 - 公众号接入接入
10. 商业版新增 - 自助开票申请
11. 商业版新增 - SSO 定制
12. 优化 - SSE 响应优化。
13. 优化 - 无 SSL 证书情况下,优化复制。
14. 优化 - 单选框打开后自动滚动到选中的位置。
15. 优化 - 知识库集合禁用,目录禁用会递归修改其下所有 children 的禁用状态。
16. 优化 - 节点选择,避免切换 tab 时候,path 加载报错。
17. 优化 - 最新 React Markdown 组件,支持 Base64 图片。
18. 优化 - 知识库列表 UI。
19. 优化 - 知识库详情页 UI。
20. 优化 - 支持无网络配置情况下运行。
21. 优化 - 部分全局变量,增加数据类型约束。
22. 修复 - 全局变量 key 可能重复。
23. 修复 - Prompt 模式调用工具,stream=false 模式下,会携带 0: 开头标记。
24. 修复 - 对话日志鉴权问题:仅为 APP 管理员的用户,无法查看对话日志详情。
25. 修复 - 选择 Milvus 部署时,无法导出知识库。
26. 修复 - 创建 APP 副本,无法复制系统配置。
27. 修复 - 图片识别模式下,自动解析图片链接正则不够严谨问题。
28. 修复 - 内容提取的数据类型与输出数据类型未一致。
29. 修复 - 工作流运行时间统计错误。
30. 修复 - stream 模式下,工具调用有可能出现 undefined
31. 修复 - 全局变量在 API 中无法持久化。
32. 修复 - OpenAPI,detail=false模式下,不应该返回 tool 调用结果,仅返回文字。(可解决 cow 不适配问题)
33. 修复 - 知识库标签重复加载。
34. 修复 - Debug 模式下,循环调用边问题。
8. 新增 - 插件增加使用说明配置。
9. 商业版新增 - 飞书机器人接入
10. 商业版新增 - 公众号接入接入
11. 商业版新增 - 自助开票申请
12. 商业版新增 - SSO 定制
13. 优化 - SSE 响应优化。
14. 优化 - 无 SSL 证书情况下,优化复制。
15. 优化 - 单选框打开后自动滚动到选中的位置。
16. 优化 - 知识库集合禁用,目录禁用会递归修改其下所有 children 的禁用状态。
17. 优化 - 节点选择,避免切换 tab 时候,path 加载报错。
18. 优化 - 最新 React Markdown 组件,支持 Base64 图片。
19. 优化 - 知识库列表 UI。
20. 优化 - 知识库详情页 UI。
21. 优化 - 支持无网络配置情况下运行。
22. 优化 - 部分全局变量,增加数据类型约束。
23. 修复 - 全局变量 key 可能重复。
24. 修复 - Prompt 模式调用工具,stream=false 模式下,会携带 0: 开头标记。
25. 修复 - 对话日志鉴权问题:仅为 APP 管理员的用户,无法查看对话日志详情。
26. 修复 - 选择 Milvus 部署时,无法导出知识库。
27. 修复 - 创建 APP 副本,无法复制系统配置。
28. 修复 - 图片识别模式下,自动解析图片链接正则不够严谨问题。
29. 修复 - 内容提取的数据类型与输出数据类型未一致。
30. 修复 - 工作流运行时间统计错误。
31. 修复 - stream 模式下,工具调用有可能出现 undefined
32. 修复 - 全局变量在 API 中无法持久化。
33. 修复 - OpenAPI,detail=false模式下,不应该返回 tool 调用结果,仅返回文字。(可解决 cow 不适配问题)
34. 修复 - 知识库标签重复加载。
35. 修复 - Debug 模式下,循环调用边问题。
8 changes: 4 additions & 4 deletions packages/global/core/workflow/runtime/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,10 @@ export type DispatchNodeResponseType = {
export type DispatchNodeResultType<T> = {
[DispatchNodeResponseKeyEnum.skipHandleId]?: string[]; // skip some edge handle id
[DispatchNodeResponseKeyEnum.nodeResponse]?: DispatchNodeResponseType; // The node response detail
[DispatchNodeResponseKeyEnum.nodeDispatchUsages]?: ChatNodeUsageType[]; //
[DispatchNodeResponseKeyEnum.childrenResponses]?: DispatchNodeResultType[];
[DispatchNodeResponseKeyEnum.toolResponses]?: ToolRunResponseItemType;
[DispatchNodeResponseKeyEnum.assistantResponses]?: ChatItemValueItemType[];
[DispatchNodeResponseKeyEnum.nodeDispatchUsages]?: ChatNodeUsageType[]; // Node total usage
[DispatchNodeResponseKeyEnum.childrenResponses]?: DispatchNodeResultType[]; // Children node response
[DispatchNodeResponseKeyEnum.toolResponses]?: ToolRunResponseItemType; // Tool response
[DispatchNodeResponseKeyEnum.assistantResponses]?: ChatItemValueItemType[]; // Assistant response(Store to db)
} & T;

/* Single node props */
Expand Down
2 changes: 1 addition & 1 deletion packages/global/core/workflow/template/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { HttpNode468 } from './system/http468';
import { ToolModule } from './system/tools';
import { StopToolNode } from './system/stopTool';

import { RunAppModule } from './system/runApp/index';
import { RunAppModule } from './system/abandoned/runApp/index';
import { PluginInputModule } from './system/pluginInput';
import { PluginOutputModule } from './system/pluginOutput';
import { RunPluginModule } from './system/runPlugin';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type/node.d';
} from '../../../../node/constant';
import { FlowNodeTemplateType } from '../../../../type/node';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../../constants';
import { Input_Template_History, Input_Template_UserChatInput } from '../../input';
import { getHandleConfig } from '../../utils';
import { i18nT } from '../../../../../../web/i18n/utils';
} from '../../../../constants';
import { Input_Template_History, Input_Template_UserChatInput } from '../../../input';
import { getHandleConfig } from '../../../utils';
import { i18nT } from '../../../../../../../web/i18n/utils';

export const RunAppModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.runApp,
Expand Down
4 changes: 3 additions & 1 deletion packages/global/core/workflow/type/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export type WorkflowTemplateBasicType = {
};
export type WorkflowTemplateType = {
id: string;
parentId?: string;
parentId?: ParentIdType;
isFolder?: boolean;

name: string;
Expand Down Expand Up @@ -62,6 +62,8 @@ export type TemplateMarketListItemType = {

// system plugin
export type SystemPluginTemplateItemType = WorkflowTemplateType & {
customWorkflow?: string;

templateType: FlowNodeTemplateTypeEnum;
isTool?: boolean;

Expand Down
12 changes: 8 additions & 4 deletions packages/global/core/workflow/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { IfElseResultEnum } from './template/system/ifElse/constant';
import { RuntimeNodeItemType } from './runtime/type';
import { getReferenceVariableValue } from './runtime/utils';
import { Input_Template_History, Input_Template_UserChatInput } from './template/input';
import { i18nT } from '../../../web/i18n/utils';

export const getHandleId = (nodeId: string, type: 'source' | 'target', key: string) => {
return `${nodeId}-${type}-${key}`;
Expand Down Expand Up @@ -254,8 +255,8 @@ export const appData2FlowNodeIO = ({
id: NodeOutputKeyEnum.history,
key: NodeOutputKeyEnum.history,
required: true,
label: 'core.module.output.label.New context',
description: 'core.module.output.description.New context',
label: i18nT('common:core.module.output.label.New context'),
description: i18nT('common:core.module.output.description.New context'),
valueType: WorkflowIOValueTypeEnum.chatHistory,
valueDesc: chatHistoryValueDesc,
type: FlowNodeOutputTypeEnum.static
Expand All @@ -264,8 +265,8 @@ export const appData2FlowNodeIO = ({
id: NodeOutputKeyEnum.answerText,
key: NodeOutputKeyEnum.answerText,
required: false,
label: 'core.module.output.label.Ai response content',
description: 'core.module.output.description.Ai response content',
label: i18nT('common:core.module.output.label.Ai response content'),
description: i18nT('common:core.module.output.description.Ai response content'),
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
Expand Down Expand Up @@ -325,6 +326,9 @@ export const updatePluginInputByVariables = (
);
};

/* Remove pluginInput variables from global variables
(completions api: Plugin input get value from global variables)
*/
export const removePluginInputVariables = (
variables: Record<string, any>,
nodes: RuntimeNodeItemType[]
Expand Down
3 changes: 2 additions & 1 deletion packages/service/core/app/plugin/systemPluginSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const SystemPluginSchema = new Schema({
currentCost: {
type: Number,
default: 0
}
},
customConfig: Object
});

SystemPluginSchema.index({ pluginId: 1 });
Expand Down
16 changes: 15 additions & 1 deletion packages/service/core/app/plugin/type.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type';
import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants';
import {
SystemPluginTemplateItemType,
WorkflowTemplateBasicType
} from '@fastgpt/global/core/workflow/type';

export type SystemPluginConfigSchemaType = {
pluginId: string;
Expand All @@ -7,4 +11,14 @@ export type SystemPluginConfigSchemaType = {
currentCost: number;
isActive: boolean;
inputConfig: SystemPluginTemplateItemType['inputConfig'];

customConfig?: {
name: string;
avatar: string;
intro?: string;
version: string;
weight?: number;
workflow: WorkflowTemplateBasicType;
templateType: FlowNodeTemplateTypeEnum;
};
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* Abandoned */
import type { ChatItemType } from '@fastgpt/global/core/chat/type.d';
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
import { SelectAppItemType } from '@fastgpt/global/core/workflow/template/system/runApp/type';
import { SelectAppItemType } from '@fastgpt/global/core/workflow/template/system/abandoned/runApp/type';
import { dispatchWorkFlow } from '../index';
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from '@fastgpt/global/core/workflow/runtime/utils';
import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import { getHistories } from '../utils';
import { filterSystemVariables, getHistories } from '../utils';
import { chatValue2RuntimePrompt, runtimePrompt2ChatsValue } from '@fastgpt/global/core/chat/adapt';
import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type';
import { authAppByTmbId } from '../../../../support/permission/app/auth';
Expand All @@ -34,10 +34,11 @@ export const dispatchRunAppNode = async (props: Props): Promise<Response> => {
query,
node: { pluginId },
workflowStreamResponse,
params
params,
variables
} = props;

const { userChatInput, history, ...variables } = params;
const { userChatInput, history, ...childrenAppVariables } = params;
if (!userChatInput) {
return Promise.reject('Input is empty');
}
Expand All @@ -63,6 +64,13 @@ export const dispatchRunAppNode = async (props: Props): Promise<Response> => {
const chatHistories = getHistories(history, histories);
const { files } = chatValue2RuntimePrompt(query);

// Concat variables
const systemVariables = filterSystemVariables(variables);
const childrenRunVariables = {
...systemVariables,
...childrenAppVariables
};

const { flowResponses, flowUsages, assistantResponses } = await dispatchWorkFlow({
...props,
app: appData,
Expand All @@ -76,7 +84,7 @@ export const dispatchRunAppNode = async (props: Props): Promise<Response> => {
files,
text: userChatInput
}),
variables: variables
variables: childrenRunVariables
});

const completeMessages = chatHistories.concat([
Expand Down
9 changes: 5 additions & 4 deletions packages/service/core/workflow/dispatch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { dispatchAnswer } from './tools/answer';
import { dispatchClassifyQuestion } from './agent/classifyQuestion';
import { dispatchContentExtract } from './agent/extract';
import { dispatchHttp468Request } from './tools/http468';
import { dispatchAppRequest } from './tools/runApp';
import { dispatchAppRequest } from './abandoned/runApp';
import { dispatchQueryExtension } from './tools/queryExternsion';
import { dispatchRunPlugin } from './plugin/run';
import { dispatchPluginInput } from './plugin/runInput';
Expand Down Expand Up @@ -63,7 +63,7 @@ import {
InteractiveNodeResponseItemType,
UserSelectInteractive
} from '@fastgpt/global/core/workflow/template/system/userSelect/type';
import { dispatchRunAppNode } from './agent/runAppModule';
import { dispatchRunAppNode } from './agent/runApp';

const callbackMap: Record<FlowNodeTypeEnum, Function> = {
[FlowNodeTypeEnum.workflowStart]: dispatchWorkflowStart,
Expand All @@ -74,7 +74,6 @@ const callbackMap: Record<FlowNodeTypeEnum, Function> = {
[FlowNodeTypeEnum.classifyQuestion]: dispatchClassifyQuestion,
[FlowNodeTypeEnum.contentExtract]: dispatchContentExtract,
[FlowNodeTypeEnum.httpRequest468]: dispatchHttp468Request,
[FlowNodeTypeEnum.runApp]: dispatchAppRequest,
[FlowNodeTypeEnum.appModule]: dispatchRunAppNode,
[FlowNodeTypeEnum.pluginModule]: dispatchRunPlugin,
[FlowNodeTypeEnum.pluginInput]: dispatchPluginInput,
Expand All @@ -95,7 +94,9 @@ const callbackMap: Record<FlowNodeTypeEnum, Function> = {
[FlowNodeTypeEnum.systemConfig]: dispatchSystemConfig,
[FlowNodeTypeEnum.pluginConfig]: () => Promise.resolve(),
[FlowNodeTypeEnum.emptyNode]: () => Promise.resolve(),
[FlowNodeTypeEnum.globalVariable]: () => Promise.resolve()
[FlowNodeTypeEnum.globalVariable]: () => Promise.resolve(),

[FlowNodeTypeEnum.runApp]: dispatchAppRequest // abandoned
};

type Props = ChatDispatchProps & {
Expand Down
49 changes: 24 additions & 25 deletions packages/service/core/workflow/dispatch/plugin/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import {
storeNodes2RuntimeNodes
} from '@fastgpt/global/core/workflow/runtime/utils';
import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type';
import { updateToolInputValue } from '../agent/runTool/utils';
import { authPluginByTmbId } from '../../../../support/permission/app/auth';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { computedPluginUsage } from '../../../app/plugin/utils';
import { filterSystemVariables } from '../utils';

type RunPluginProps = ModuleDispatchProps<{
[key: string]: any;
Expand All @@ -25,7 +25,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
app: workflowApp,
mode,
teamId,
params: data
params: data // Plugin input
} = props;

if (!pluginId) {
Expand All @@ -41,32 +41,31 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi

const plugin = await getPluginRuntimeById(pluginId);

// concat dynamic inputs
const inputModule = plugin.nodes.find(
(item) => item.flowNodeType === FlowNodeTypeEnum.pluginInput
);
if (!inputModule) return Promise.reject('Plugin error, It has no set input.');
const runtimeNodes = storeNodes2RuntimeNodes(
plugin.nodes,
getWorkflowEntryNodeIds(plugin.nodes)
).map((node) => {
// Update plugin input value
if (node.flowNodeType === FlowNodeTypeEnum.pluginInput) {
return {
...node,
showStatus: false,
inputs: node.inputs.map((input) => ({
...input,
value: data[input.key] ?? input.value
}))
};
}
return {
...node,
showStatus: false
};
});

const { flowResponses, flowUsages, assistantResponses } = await dispatchWorkFlow({
...props,
runtimeNodes: storeNodes2RuntimeNodes(plugin.nodes, getWorkflowEntryNodeIds(plugin.nodes)).map(
(node) => {
if (node.flowNodeType === FlowNodeTypeEnum.pluginInput) {
return {
...node,
showStatus: false,
inputs: updateToolInputValue({
inputs: node.inputs,
params: data
})
};
}
return {
...node,
showStatus: false
};
}
),
variables: filterSystemVariables(props.variables),
runtimeNodes,
runtimeEdges: initWorkflowEdgeStatus(plugin.edges)
});

Expand Down
9 changes: 9 additions & 0 deletions packages/service/core/workflow/dispatch/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ export const removeSystemVariable = (variables: Record<string, any>) => {

return copyVariables;
};
export const filterSystemVariables = (variables: Record<string, any>) => {
return {
appId: variables.appId,
chatId: variables.chatId,
responseChatItemId: variables.responseChatItemId,
histories: variables.histories,
cTime: variables.cTime
};
};

export const formatHttpError = (error: any) => {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ const RenderInput = () => {
rounded={'md'}
fontSize={'sm'}
color={'myGray.600'}
mb={4}
>
<Markdown source={chatConfig.instruction} />
</Box>
Expand Down
Loading

0 comments on commit 060492d

Please sign in to comment.