4.8 preview (#1288)

* Revert "lafAccount add pat & re request when token invalid (#76)" (#77)

This reverts commit 83d85dfe37adcaef4833385ea52ee79fd84720be.

* perf: workflow ux

* system config

* Newflow (#89)

* docs: Add doc for Xinference (#1266)

Signed-off-by: Carson Yang <yangchuansheng33@gmail.com>

* Revert "lafAccount add pat & re request when token invalid (#76)" (#77)

This reverts commit 83d85dfe37adcaef4833385ea52ee79fd84720be.

* perf: workflow ux

* system config

* Revert "lafAccount add pat & re request when token invalid (#76)" (#77)

This reverts commit 83d85dfe37adcaef4833385ea52ee79fd84720be.

* Revert "lafAccount add pat & re request when token invalid (#76)" (#77)

This reverts commit 83d85dfe37adcaef4833385ea52ee79fd84720be.

* Revert "lafAccount add pat & re request when token invalid (#76)" (#77)

This reverts commit 83d85dfe37adcaef4833385ea52ee79fd84720be.

* rename code

* move code

* update flow

* input type selector

* perf: workflow runtime

* feat: node adapt newflow

* feat: adapt plugin

* feat: 360 connection

* check workflow

* perf: flow 性能

* change plugin input type (#81)

* change plugin input type

* plugin label mode

* perf: nodecard

* debug

* perf: debug ui

* connection ui

* change workflow ui (#82)

* feat: workflow debug

* adapt openAPI for new workflow (#83)

* adapt openAPI for new workflow

* i18n

* perf: plugin debug

* plugin input ui

* delete

* perf: global variable select

* fix rebase

* perf: workflow performance

* feat: input render type icon

* input icon

* adapt flow (#84)

* adapt newflow

* temp

* temp

* fix

* feat: app schedule trigger

* feat: app schedule trigger

* perf: schedule ui

* feat: ioslatevm run js code

* perf: workflow varialbe table ui

* feat: adapt simple mode

* feat: adapt input params

* output

* feat: adapt tamplate

* fix: ts

* add if-else module (#86)

* perf: worker

* if else node

* perf: tiktoken worker

* fix: ts

* perf: tiktoken

* fix if-else node (#87)

* fix if-else node

* type

* fix

* perf: audio render

* perf: Parallel worker

* log

* perf: if else node

* adapt plugin

* prompt

* perf: reference ui

* reference ui

* handle ux

* template ui and plugin tool

* adapt v1 workflow

* adapt v1 workflow completions

* perf: time variables

* feat: workflow keyboard shortcuts

* adapt v1 workflow

* update workflow example doc (#88)

* fix: simple mode select tool

---------

Signed-off-by: Carson Yang <yangchuansheng33@gmail.com>
Co-authored-by: Carson Yang <yangchuansheng33@gmail.com>
Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>

* doc

* perf: extract node

* extra node field

* update plugin version

* doc

* variable

* change doc & fix prompt editor (#90)

* fold workflow code

* value type label

---------

Signed-off-by: Carson Yang <yangchuansheng33@gmail.com>
Co-authored-by: Carson Yang <yangchuansheng33@gmail.com>
Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
Archer
2024-04-25 17:51:20 +08:00
committed by GitHub
parent b08d81f887
commit 439c819ff1
505 changed files with 23570 additions and 18215 deletions

View File

@@ -41,20 +41,22 @@ export const Prompt_ExtractJson = `你可以从 <对话记录></对话记录>
</对话记录>
`;
export const Prompt_CQJson = `我会给你几个问题类型请参考背景知识可能为空和对话记录判断我“本次问题”的类型并返回一个问题“类型ID”:
<问题类型>
export const Prompt_CQJson = `请帮我执行一个“问题分类”任务,将问题分类为以下几种类型之一:
"""
{{typeList}}
</问题类型>
"""
<背景知识>
## 背景知识
{{systemPrompt}}
</背景知识>
<对话记录>
## 对话记录
{{history}}
</对话记录>
Human"{{question}}"
## 开始任务
现在,我们开始分类,我会给你一个"问题"请结合背景知识和对话记录将问题分类到对应的类型中并返回类型ID。
问题:"{{question}}"
类型ID=
`;

View File

@@ -7,6 +7,7 @@ export type CreateAppParams = {
avatar?: string;
type?: `${AppTypeEnum}`;
modules: AppSchema['modules'];
edges?: AppSchema['edges'];
};
export interface AppUpdateParams {
@@ -15,6 +16,7 @@ export interface AppUpdateParams {
avatar?: string;
intro?: string;
modules?: AppSchema['modules'];
edges?: AppSchema['edges'];
permission?: AppSchema['permission'];
teamTags?: AppSchema['teamTags'];
}

View File

@@ -1,23 +1,30 @@
import type { FlowNodeTemplateType, ModuleItemType } from '../module/type.d';
import type { FlowNodeTemplateType, StoreNodeItemType } from '../workflow/type';
import { AppTypeEnum } from './constants';
import { PermissionTypeEnum } from '../../support/permission/constant';
import type { DatasetModuleProps } from '../module/node/type.d';
import { VariableInputEnum } from '../module/constants';
import { SelectedDatasetType } from '../module/api';
import { VariableInputEnum } from '../workflow/constants';
import { SelectedDatasetType } from '../workflow/api';
import { DatasetSearchModeEnum } from '../dataset/constants';
import { TeamTagSchema as TeamTagsSchemaType } from '@fastgpt/global/support/user/team/type.d';
import { StoreEdgeItemType } from 'core/workflow/type/edge';
export interface AppSchema {
_id: string;
userId: string;
teamId: string;
tmbId: string;
name: string;
type: `${AppTypeEnum}`;
version?: 'v1' | 'v2';
avatar: string;
intro: string;
updateTime: number;
modules: ModuleItemType[];
modules: StoreNodeItemType[];
edges: StoreEdgeItemType[];
// App system config
scheduledTriggerConfig?: AppScheduledTriggerConfigType | null;
scheduledTriggerNextTime?: Date;
permission: `${PermissionTypeEnum}`;
inited?: boolean;
teamTags: string[];
@@ -79,10 +86,19 @@ export type AppSimpleEditFormType = {
speed?: number | undefined;
};
whisper: AppWhisperConfigType;
scheduleTrigger: AppScheduledTriggerConfigType | null;
};
};
/* app function config */
export type SettingAIDataType = {
model: string;
temperature: number;
maxToken: number;
isResponseAnswerText?: boolean;
maxHistories?: number;
};
// variable
export type VariableItemType = {
id: string;
@@ -106,3 +122,9 @@ export type AppWhisperConfigType = {
autoSend: boolean;
autoTTSResponse: boolean;
};
// interval timer
export type AppScheduledTriggerConfigType = {
cronString: string;
timezone: string;
defaultPrompt: string;
};

View File

@@ -1,13 +1,9 @@
import type { AppSimpleEditFormType } from '../app/type';
import { FlowNodeTypeEnum } from '../module/node/constant';
import {
ModuleOutputKeyEnum,
ModuleInputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../module/constants';
import type { FlowNodeInputItemType } from '../module/node/type.d';
import { getGuideModule, splitGuideModule } from '../module/utils';
import { ModuleItemType } from '../module/type.d';
import { FlowNodeTypeEnum } from '../workflow/node/constant';
import { NodeInputKeyEnum, FlowNodeTemplateTypeEnum } from '../workflow/constants';
import type { FlowNodeInputItemType } from '../workflow/type/io.d';
import { getGuideModule, splitGuideModule } from '../workflow/utils';
import { StoreNodeItemType } from '../workflow/type';
import { DatasetSearchModeEnum } from '../dataset/constants';
import { defaultWhisperConfig } from './constants';
@@ -38,97 +34,104 @@ export const getDefaultAppForm = (): AppSimpleEditFormType => {
tts: {
type: 'web'
},
whisper: defaultWhisperConfig
whisper: defaultWhisperConfig,
scheduleTrigger: null
}
};
};
/* format app modules to edit form */
export const appModules2Form = ({ modules }: { modules: ModuleItemType[] }) => {
/* format app nodes to edit form */
export const appWorkflow2Form = ({ nodes }: { nodes: StoreNodeItemType[] }) => {
const defaultAppForm = getDefaultAppForm();
const findInputValueByKey = (inputs: FlowNodeInputItemType[], key: string) => {
return inputs.find((item) => item.key === key)?.value;
};
modules.forEach((module) => {
nodes.forEach((node) => {
if (
module.flowType === FlowNodeTypeEnum.chatNode ||
module.flowType === FlowNodeTypeEnum.tools
node.flowNodeType === FlowNodeTypeEnum.chatNode ||
node.flowNodeType === FlowNodeTypeEnum.tools
) {
defaultAppForm.aiSettings.model = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.aiModel
);
defaultAppForm.aiSettings.model = findInputValueByKey(node.inputs, NodeInputKeyEnum.aiModel);
defaultAppForm.aiSettings.systemPrompt = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.aiSystemPrompt
node.inputs,
NodeInputKeyEnum.aiSystemPrompt
);
defaultAppForm.aiSettings.temperature = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.aiChatTemperature
node.inputs,
NodeInputKeyEnum.aiChatTemperature
);
defaultAppForm.aiSettings.maxToken = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.aiChatMaxToken
node.inputs,
NodeInputKeyEnum.aiChatMaxToken
);
defaultAppForm.aiSettings.maxHistories = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.history
node.inputs,
NodeInputKeyEnum.history
);
} else if (module.flowType === FlowNodeTypeEnum.datasetSearchNode) {
} else if (node.flowNodeType === FlowNodeTypeEnum.datasetSearchNode) {
defaultAppForm.dataset.datasets = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.datasetSelectList
node.inputs,
NodeInputKeyEnum.datasetSelectList
);
defaultAppForm.dataset.similarity = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.datasetSimilarity
node.inputs,
NodeInputKeyEnum.datasetSimilarity
);
defaultAppForm.dataset.limit = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.datasetMaxTokens
node.inputs,
NodeInputKeyEnum.datasetMaxTokens
);
defaultAppForm.dataset.searchMode =
findInputValueByKey(module.inputs, ModuleInputKeyEnum.datasetSearchMode) ||
findInputValueByKey(node.inputs, NodeInputKeyEnum.datasetSearchMode) ||
DatasetSearchModeEnum.embedding;
defaultAppForm.dataset.usingReRank = !!findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.datasetSearchUsingReRank
node.inputs,
NodeInputKeyEnum.datasetSearchUsingReRank
);
defaultAppForm.dataset.datasetSearchUsingExtensionQuery = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.datasetSearchUsingExtensionQuery
node.inputs,
NodeInputKeyEnum.datasetSearchUsingExtensionQuery
);
defaultAppForm.dataset.datasetSearchExtensionModel = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.datasetSearchExtensionModel
node.inputs,
NodeInputKeyEnum.datasetSearchExtensionModel
);
defaultAppForm.dataset.datasetSearchExtensionBg = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.datasetSearchExtensionBg
node.inputs,
NodeInputKeyEnum.datasetSearchExtensionBg
);
} else if (module.flowType === FlowNodeTypeEnum.userGuide) {
const { welcomeText, variableModules, questionGuide, ttsConfig, whisperConfig } =
splitGuideModule(getGuideModule(modules));
} else if (node.flowNodeType === FlowNodeTypeEnum.systemConfig) {
const {
welcomeText,
variableModules,
questionGuide,
ttsConfig,
whisperConfig,
scheduledTriggerConfig
} = splitGuideModule(getGuideModule(nodes));
defaultAppForm.userGuide = {
welcomeText: welcomeText,
variables: variableModules,
questionGuide: questionGuide,
tts: ttsConfig,
whisper: whisperConfig
whisper: whisperConfig,
scheduleTrigger: scheduledTriggerConfig
};
} else if (module.flowType === FlowNodeTypeEnum.pluginModule) {
} else if (node.flowNodeType === FlowNodeTypeEnum.pluginModule) {
if (!node.pluginId) return;
defaultAppForm.selectedTools.push({
id: module.inputs.find((input) => input.key === ModuleInputKeyEnum.pluginId)?.value || '',
name: module.name,
avatar: module.avatar,
intro: module.intro || '',
flowType: module.flowType,
showStatus: module.showStatus,
inputs: module.inputs,
outputs: module.outputs,
id: node.pluginId,
name: node.name,
avatar: node.avatar,
intro: node.intro || '',
flowNodeType: node.flowNodeType,
showStatus: node.showStatus,
inputs: node.inputs,
outputs: node.outputs,
templateType: FlowNodeTemplateTypeEnum.other
});
}

View File

@@ -1,4 +1,4 @@
import { ClassifyQuestionAgentItemType } from '../module/type';
import { ClassifyQuestionAgentItemType } from '../workflow/type';
import { SearchDataResponseItemType } from '../dataset/type';
import {
ChatFileTypeEnum,
@@ -7,14 +7,14 @@ import {
ChatSourceEnum,
ChatStatusEnum
} from './constants';
import { FlowNodeTypeEnum } from '../module/node/constant';
import { ModuleOutputKeyEnum } from '../module/constants';
import { DispatchNodeResponseKeyEnum } from '../module/runtime/constants';
import { FlowNodeTypeEnum } from '../workflow/node/constant';
import { NodeOutputKeyEnum } from '../workflow/constants';
import { DispatchNodeResponseKeyEnum } from '../workflow/runtime/constants';
import { AppSchema } from '../app/type';
import type { AppSchema as AppType } from '@fastgpt/global/core/app/type.d';
import { DatasetSearchModeEnum } from '../dataset/constants';
import { ChatBoxInputType } from '../../../../projects/app/src/components/ChatBox/type';
import { DispatchNodeResponseType } from '../module/runtime/type.d';
import { DispatchNodeResponseType } from '../workflow/runtime/type.d';
export type ChatSchema = {
_id: string;
@@ -136,6 +136,7 @@ export type ChatHistoryItemType = HistoryItemType & {
/* ------- response data ------------ */
export type ChatHistoryItemResType = DispatchNodeResponseType & {
nodeId: string;
moduleType: `${FlowNodeTypeEnum}`;
moduleName: string;
};

View File

@@ -1,5 +1,5 @@
import { DispatchNodeResponseType } from '../module/runtime/type';
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../module/node/constant';
import { DispatchNodeResponseType } from '../workflow/runtime/type';
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../workflow/node/constant';
import { ChatItemValueTypeEnum, ChatRoleEnum } from './constants';
import { ChatHistoryItemResType, ChatItemType } from './type.d';

View File

@@ -1,4 +1,3 @@
import { countPromptTokens } from '../../../common/string/tiktoken';
import { SearchScoreTypeEnum } from '../constants';
import { SearchDataResponseItemType } from '../type';
@@ -71,25 +70,3 @@ export const datasetSearchResultConcat = (
return item;
});
};
export const filterSearchResultsByMaxChars = (
list: SearchDataResponseItemType[],
maxTokens: number
) => {
const results: SearchDataResponseItemType[] = [];
let totalTokens = 0;
for (let i = 0; i < list.length; i++) {
const item = list[i];
totalTokens += countPromptTokens(item.q + item.a);
if (totalTokens > maxTokens + 500) {
break;
}
results.push(item);
if (totalTokens > maxTokens) {
break;
}
}
return results.length === 0 ? list.slice(0, 1) : results;
};

View File

@@ -1,70 +0,0 @@
export enum FlowNodeInputTypeEnum {
triggerAndFinish = 'triggerAndFinish',
systemInput = 'systemInput', // history, userChatInput, variableInput
input = 'input', // one line input
numberInput = 'numberInput',
select = 'select',
slider = 'slider',
target = 'target', // data input
switch = 'switch',
// editor
textarea = 'textarea',
JSONEditor = 'JSONEditor',
addInputParam = 'addInputParam', // params input
selectApp = 'selectApp',
// chat special input
aiSettings = 'aiSettings',
// ai model select
selectLLMModel = 'selectLLMModel',
settingLLMModel = 'settingLLMModel',
// dataset special input
selectDataset = 'selectDataset',
selectDatasetParamsModal = 'selectDatasetParamsModal',
settingDatasetQuotePrompt = 'settingDatasetQuotePrompt',
hidden = 'hidden',
custom = 'custom'
}
export enum FlowNodeOutputTypeEnum {
answer = 'answer',
source = 'source',
hidden = 'hidden',
addOutputParam = 'addOutputParam'
}
export enum FlowNodeTypeEnum {
userGuide = 'userGuide',
questionInput = 'questionInput',
historyNode = 'historyNode',
chatNode = 'chatNode',
datasetSearchNode = 'datasetSearchNode',
datasetConcatNode = 'datasetConcatNode',
answerNode = 'answerNode',
classifyQuestion = 'classifyQuestion',
contentExtract = 'contentExtract',
httpRequest = 'httpRequest',
httpRequest468 = 'httpRequest468',
runApp = 'app',
pluginModule = 'pluginModule',
pluginInput = 'pluginInput',
pluginOutput = 'pluginOutput',
queryExtension = 'cfr',
tools = 'tools',
stopTool = 'stopTool',
lafModule = 'lafModule'
// abandon
}
export const EDGE_TYPE = 'default';

View File

@@ -1,128 +0,0 @@
import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from './constant';
import { ModuleIOValueTypeEnum, ModuleInputKeyEnum, ModuleOutputKeyEnum } from '../constants';
import { SelectedDatasetType } from '../api';
import { EditInputFieldMap, EditOutputFieldMap } from './type';
import { LLMModelTypeEnum } from '../../ai/constants';
export type FlowNodeChangeProps = {
moduleId: string;
type:
| 'attr' // key: attr, value: new value
| 'updateInput' // key: update input key, value: new input value
| 'replaceInput' // key: old input key, value: new input value
| 'addInput' // key: null, value: new input value
| 'delInput' // key: delete input key, value: null
| 'updateOutput' // key: update output key, value: new output value
| 'replaceOutput' // key: old output key, value: new output value
| 'addOutput' // key: null, value: new output value
| 'delOutput'; // key: delete output key, value: null
key?: string;
value?: any;
index?: number;
};
export type FlowNodeInputItemType = {
valueType?: `${ModuleIOValueTypeEnum}`; // data type
type: `${FlowNodeInputTypeEnum}`; // Node Type. Decide on a render style
key: `${ModuleInputKeyEnum}` | string;
value?: any;
label: string;
description?: string;
required?: boolean;
toolDescription?: string; // If this field is not empty, it is entered as a tool
edit?: boolean; // Whether to allow editing
editField?: EditInputFieldMap;
defaultEditField?: EditNodeFieldType;
connected?: boolean; // There are incoming data
showTargetInApp?: boolean;
showTargetInPlugin?: boolean;
hideInApp?: boolean;
hideInPlugin?: boolean;
placeholder?: string; // input,textarea
list?: { label: string; value: any }[]; // select
markList?: { label: string; value: any }[]; // slider
step?: number; // slider
max?: number; // slider, number input
min?: number; // slider, number input
llmModelType?: `${LLMModelTypeEnum}`;
};
export type FlowNodeOutputTargetItemType = {
moduleId: string;
key: string;
};
export type FlowNodeOutputItemType = {
type?: `${FlowNodeOutputTypeEnum}`;
key: `${ModuleOutputKeyEnum}` | string;
valueType?: `${ModuleIOValueTypeEnum}`;
label?: string;
description?: string;
required?: boolean;
defaultValue?: any;
edit?: boolean;
editField?: EditOutputFieldMap;
defaultEditField?: EditNodeFieldType;
targets: FlowNodeOutputTargetItemType[];
};
/* --------------- edit field ------------------- */
export type EditInputFieldMap = EditOutputFieldMap & {
inputType?: boolean;
required?: boolean;
isToolInput?: boolean;
};
export type EditOutputFieldMap = {
name?: boolean;
key?: boolean;
description?: boolean;
dataType?: boolean;
defaultValue?: boolean;
};
export type EditNodeFieldType = {
inputType?: `${FlowNodeInputTypeEnum}`; // input type
outputType?: `${FlowNodeOutputTypeEnum}`;
required?: boolean;
key?: string;
label?: string;
description?: string;
valueType?: `${ModuleIOValueTypeEnum}`;
isToolInput?: boolean;
defaultValue?: string;
};
/* ------------- item type --------------- */
export type SettingAIDataType = {
model: string;
temperature: number;
maxToken: number;
isResponseAnswerText?: boolean;
maxHistories?: number;
};
/* ai chat modules props */
export type AIChatModuleProps = {
[ModuleInputKeyEnum.aiModel]: string;
[ModuleInputKeyEnum.aiSystemPrompt]?: string;
[ModuleInputKeyEnum.aiChatTemperature]: number;
[ModuleInputKeyEnum.aiChatMaxToken]: number;
[ModuleInputKeyEnum.aiChatIsResponseText]: boolean;
[ModuleInputKeyEnum.aiChatQuoteTemplate]?: string;
[ModuleInputKeyEnum.aiChatQuotePrompt]?: string;
};
export type DatasetModuleProps = {
[ModuleInputKeyEnum.datasetSelectList]: SelectedDatasetType;
[ModuleInputKeyEnum.datasetSimilarity]: number;
[ModuleInputKeyEnum.datasetMaxTokens]: number;
[ModuleInputKeyEnum.datasetStartReRank]: boolean;
};

View File

@@ -1,31 +0,0 @@
import { ChatCompletionRequestMessageRoleEnum } from '../../ai/constants';
export const textAdaptGptResponse = ({
text,
model = '',
finish_reason = null,
extraData = {}
}: {
model?: string;
text: string | null;
finish_reason?: null | 'stop';
extraData?: Object;
}) => {
return JSON.stringify({
...extraData,
id: '',
object: '',
created: 0,
model,
choices: [
{
delta:
text === null
? {}
: { role: ChatCompletionRequestMessageRoleEnum.Assistant, content: text },
index: 0,
finish_reason
}
]
});
};

View File

@@ -1,101 +0,0 @@
import type { FlowNodeInputItemType } from '../node/type.d';
import { DYNAMIC_INPUT_KEY, ModuleInputKeyEnum } from '../constants';
import { FlowNodeInputTypeEnum } from '../node/constant';
import { ModuleIOValueTypeEnum } from '../constants';
import { chatNodeSystemPromptTip } from './tip';
export const Input_Template_Switch: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.switch,
type: FlowNodeInputTypeEnum.hidden,
label: '',
description: 'core.module.input.description.Trigger',
valueType: ModuleIOValueTypeEnum.any,
showTargetInApp: true,
showTargetInPlugin: true
};
export const Input_Template_History: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.history,
type: FlowNodeInputTypeEnum.numberInput,
label: 'core.module.input.label.chat history',
required: true,
min: 0,
max: 30,
valueType: ModuleIOValueTypeEnum.chatHistory,
value: 6,
showTargetInApp: true,
showTargetInPlugin: true
};
export const Input_Template_UserChatInput: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.userChatInput,
type: FlowNodeInputTypeEnum.custom,
label: '',
required: true,
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: true,
showTargetInPlugin: true
};
export const Input_Template_AddInputParam: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.addInputParam,
type: FlowNodeInputTypeEnum.addInputParam,
valueType: ModuleIOValueTypeEnum.any,
label: '',
required: false,
showTargetInApp: false,
showTargetInPlugin: false
};
export const Input_Template_DynamicInput: FlowNodeInputItemType = {
key: DYNAMIC_INPUT_KEY,
type: FlowNodeInputTypeEnum.target,
valueType: ModuleIOValueTypeEnum.any,
label: 'core.module.inputType.dynamicTargetInput',
description: 'core.module.input.description.dynamic input',
required: false,
showTargetInApp: false,
showTargetInPlugin: true,
hideInApp: true
};
export const Input_Template_SelectAIModel: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.aiModel,
type: FlowNodeInputTypeEnum.selectLLMModel,
label: 'core.module.input.label.aiModel',
required: true,
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: false,
showTargetInPlugin: false
};
export const Input_Template_SettingAiModel: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.aiModel,
type: FlowNodeInputTypeEnum.settingLLMModel,
label: 'core.module.input.label.aiModel',
required: true,
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: false,
showTargetInPlugin: false
};
export const Input_Template_System_Prompt: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.aiSystemPrompt,
type: FlowNodeInputTypeEnum.textarea,
max: 3000,
valueType: ModuleIOValueTypeEnum.string,
label: 'core.ai.Prompt',
description: chatNodeSystemPromptTip,
placeholder: chatNodeSystemPromptTip,
showTargetInApp: true,
showTargetInPlugin: true
};
export const Input_Template_Dataset_Quote: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.aiChatDatasetQuote,
type: FlowNodeInputTypeEnum.settingDatasetQuotePrompt,
label: '知识库引用',
description: 'core.module.Dataset quote.Input description',
valueType: ModuleIOValueTypeEnum.datasetQuote,
showTargetInApp: true,
showTargetInPlugin: true
};

View File

@@ -1,29 +0,0 @@
import type { FlowNodeOutputItemType } from '../node/type';
import { ModuleOutputKeyEnum } from '../constants';
import { FlowNodeOutputTypeEnum } from '../node/constant';
import { ModuleIOValueTypeEnum } from '../constants';
export const Output_Template_UserChatInput: FlowNodeOutputItemType = {
key: ModuleOutputKeyEnum.userChatInput,
label: 'core.module.input.label.user question',
type: FlowNodeOutputTypeEnum.hidden,
valueType: ModuleIOValueTypeEnum.string,
targets: []
};
export const Output_Template_Finish: FlowNodeOutputItemType = {
key: ModuleOutputKeyEnum.finish,
label: '',
description: '',
valueType: ModuleIOValueTypeEnum.boolean,
type: FlowNodeOutputTypeEnum.hidden,
targets: []
};
export const Output_Template_AddOutput: FlowNodeOutputItemType = {
key: ModuleOutputKeyEnum.addOutputParam,
type: FlowNodeOutputTypeEnum.addOutputParam,
valueType: ModuleIOValueTypeEnum.any,
label: '',
targets: []
};

View File

@@ -1,112 +0,0 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../../constants';
import {
Input_Template_AddInputParam,
Input_Template_DynamicInput,
Input_Template_Switch
} from '../../input';
import { Output_Template_AddOutput, Output_Template_Finish } from '../../output';
export const HttpModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.httpRequest,
templateType: FlowNodeTemplateTypeEnum.externalCall,
flowType: FlowNodeTypeEnum.httpRequest,
avatar: '/imgs/module/http.png',
name: 'core.module.template.Http request',
intro:
'该Http模块已被弃用将于2024/3/31 不再提供服务。请尽快删除该模块并重新添加新的 Http 模块。',
showStatus: true,
inputs: [
Input_Template_Switch,
{
key: ModuleInputKeyEnum.httpMethod,
type: FlowNodeInputTypeEnum.select,
valueType: ModuleIOValueTypeEnum.string,
label: 'core.module.input.label.Http Request Method',
value: 'POST',
list: [
{
label: 'GET',
value: 'GET'
},
{
label: 'POST',
value: 'POST'
}
],
required: true,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.httpReqUrl,
type: FlowNodeInputTypeEnum.input,
valueType: ModuleIOValueTypeEnum.string,
label: 'core.module.input.label.Http Request Url',
description: 'core.module.input.description.Http Request Url',
placeholder: 'https://api.ai.com/getInventory',
required: false,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.httpHeaders,
type: FlowNodeInputTypeEnum.JSONEditor,
valueType: ModuleIOValueTypeEnum.string,
value: '',
label: 'core.module.input.label.Http Request Header',
description: 'core.module.input.description.Http Request Header',
placeholder: 'core.module.input.description.Http Request Header',
required: false,
showTargetInApp: false,
showTargetInPlugin: false
},
Input_Template_DynamicInput,
{
...Input_Template_AddInputParam,
editField: {
key: true,
name: true,
description: true,
required: true,
dataType: true
},
defaultEditField: {
label: '',
key: '',
description: '',
inputType: FlowNodeInputTypeEnum.target,
valueType: ModuleIOValueTypeEnum.string,
required: true
}
}
],
outputs: [
Output_Template_Finish,
{
...Output_Template_AddOutput,
editField: {
key: true,
name: true,
description: true,
dataType: true
},
defaultEditField: {
label: '',
key: '',
description: '',
outputType: FlowNodeOutputTypeEnum.source,
valueType: ModuleIOValueTypeEnum.string
}
}
]
};

View File

@@ -1,117 +0,0 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import {
Input_Template_SettingAiModel,
Input_Template_Dataset_Quote,
Input_Template_History,
Input_Template_Switch,
Input_Template_System_Prompt,
Input_Template_UserChatInput
} from '../input';
import { chatNodeSystemPromptTip } from '../tip';
import { Output_Template_Finish, Output_Template_UserChatInput } from '../output';
export const AiChatModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.chatNode,
templateType: FlowNodeTemplateTypeEnum.textAnswer,
flowType: FlowNodeTypeEnum.chatNode,
avatar: '/imgs/module/AI.png',
name: 'AI 对话',
intro: 'AI 大模型对话',
showStatus: true,
isTool: true,
inputs: [
Input_Template_Switch,
Input_Template_SettingAiModel,
// --- settings modal
{
key: ModuleInputKeyEnum.aiChatTemperature,
type: FlowNodeInputTypeEnum.hidden, // Set in the pop-up window
label: '',
value: 0,
valueType: ModuleIOValueTypeEnum.number,
min: 0,
max: 10,
step: 1,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.aiChatMaxToken,
type: FlowNodeInputTypeEnum.hidden, // Set in the pop-up window
label: '',
value: 2000,
valueType: ModuleIOValueTypeEnum.number,
min: 100,
max: 4000,
step: 50,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.aiChatIsResponseText,
type: FlowNodeInputTypeEnum.hidden,
label: '',
value: true,
valueType: ModuleIOValueTypeEnum.boolean,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.aiChatQuoteTemplate,
type: FlowNodeInputTypeEnum.hidden,
label: '',
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.aiChatQuotePrompt,
type: FlowNodeInputTypeEnum.hidden,
label: '',
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: false,
showTargetInPlugin: false
},
// settings modal ---
{
...Input_Template_System_Prompt,
label: 'core.ai.Prompt',
description: chatNodeSystemPromptTip,
placeholder: chatNodeSystemPromptTip
},
Input_Template_History,
{ ...Input_Template_UserChatInput, toolDescription: '用户问题' },
Input_Template_Dataset_Quote
],
outputs: [
Output_Template_UserChatInput,
{
key: ModuleOutputKeyEnum.history,
label: 'core.module.output.label.New context',
description: 'core.module.output.description.New context',
valueType: ModuleIOValueTypeEnum.chatHistory,
type: FlowNodeOutputTypeEnum.source,
targets: []
},
{
key: ModuleOutputKeyEnum.answerText,
label: 'core.module.output.label.Ai response content',
description: 'core.module.output.description.Ai response content',
valueType: ModuleIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.source,
targets: []
},
Output_Template_Finish
]
};

View File

@@ -1,33 +0,0 @@
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_Switch } from '../input';
import { Output_Template_Finish } from '../output';
export const AssignedAnswerModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.answerNode,
templateType: FlowNodeTemplateTypeEnum.textAnswer,
flowType: FlowNodeTypeEnum.answerNode,
avatar: '/imgs/module/reply.png',
name: '指定回复',
intro:
'该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。',
inputs: [
Input_Template_Switch,
{
key: ModuleInputKeyEnum.answerText,
type: FlowNodeInputTypeEnum.textarea,
valueType: ModuleIOValueTypeEnum.any,
label: 'core.module.input.label.Response content',
description: 'core.module.input.description.Response content',
placeholder: 'core.module.input.description.Response content',
showTargetInApp: true,
showTargetInPlugin: true
}
],
outputs: [Output_Template_Finish]
};

View File

@@ -1,94 +0,0 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import {
Input_Template_SelectAIModel,
Input_Template_History,
Input_Template_Switch
} from '../input';
import { LLMModelTypeEnum } from '../../../ai/constants';
export const ContextExtractModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.contentExtract,
templateType: FlowNodeTemplateTypeEnum.functionCall,
flowType: FlowNodeTypeEnum.contentExtract,
avatar: '/imgs/module/extract.png',
name: '文本内容提取',
intro: '可从文本中提取指定的数据例如sql语句、搜索关键词、代码等',
showStatus: true,
isTool: true,
inputs: [
Input_Template_Switch,
{
...Input_Template_SelectAIModel,
llmModelType: LLMModelTypeEnum.extractFields
},
{
key: ModuleInputKeyEnum.description,
type: FlowNodeInputTypeEnum.textarea,
valueType: ModuleIOValueTypeEnum.string,
label: '提取要求描述',
description:
'给AI一些对应的背景知识或要求描述引导AI更好的完成任务。\n该输入框可使用全局变量。',
placeholder:
'例如: \n1. 当前时间为: {{cTime}}。你是一个实验室预约助手,你的任务是帮助用户预约实验室,从文本中获取对应的预约信息。\n2. 你是谷歌搜索助手,需要从文本中提取出合适的搜索词。',
showTargetInApp: true,
showTargetInPlugin: true
},
Input_Template_History,
{
key: ModuleInputKeyEnum.contextExtractInput,
type: FlowNodeInputTypeEnum.target,
label: '需要提取的文本',
required: true,
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: true,
showTargetInPlugin: true,
toolDescription: '需要检索的内容'
},
{
key: ModuleInputKeyEnum.extractKeys,
type: FlowNodeInputTypeEnum.custom,
label: '',
valueType: ModuleIOValueTypeEnum.any,
description: "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段",
value: [], // {desc: string; key: string; required: boolean; enum: string[]}[]
showTargetInApp: false,
showTargetInPlugin: false
}
],
outputs: [
{
key: ModuleOutputKeyEnum.success,
label: '字段完全提取',
valueType: ModuleIOValueTypeEnum.boolean,
type: FlowNodeOutputTypeEnum.source,
targets: []
},
{
key: ModuleOutputKeyEnum.failed,
label: '提取字段缺失',
description: '存在一个或多个字段未提取成功。尽管使用了默认值也算缺失。',
valueType: ModuleIOValueTypeEnum.boolean,
type: FlowNodeOutputTypeEnum.source,
targets: []
},
{
key: ModuleOutputKeyEnum.contextExtractFields,
label: '完整提取结果',
description: '一个 JSON 字符串,例如:{"name:":"YY","Time":"2023/7/2 18:00"}',
valueType: ModuleIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.source,
targets: []
}
]
};

View File

@@ -1,53 +0,0 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_Dataset_Quote, Input_Template_Switch } from '../input';
import { Output_Template_Finish } from '../output';
import { getNanoid } from '../../../../common/string/tools';
export const getOneQuoteInputTemplate = (key = getNanoid()) => ({
...Input_Template_Dataset_Quote,
key,
type: FlowNodeInputTypeEnum.hidden
});
export const DatasetConcatModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.datasetConcatNode,
flowType: FlowNodeTypeEnum.datasetConcatNode,
templateType: FlowNodeTemplateTypeEnum.other,
avatar: '/imgs/module/concat.svg',
name: '知识库搜索引用合并',
intro: '可以将多个知识库搜索结果进行合并输出。使用 RRF 的合并方式进行最终排序输出。',
showStatus: false,
inputs: [
Input_Template_Switch,
{
key: ModuleInputKeyEnum.datasetMaxTokens,
type: FlowNodeInputTypeEnum.custom,
label: '最大 Tokens',
value: 1500,
valueType: ModuleIOValueTypeEnum.number,
showTargetInApp: false,
showTargetInPlugin: false
},
getOneQuoteInputTemplate('defaultQuote')
],
outputs: [
{
key: ModuleOutputKeyEnum.datasetQuoteQA,
label: 'core.module.Dataset quote.label',
type: FlowNodeOutputTypeEnum.source,
valueType: ModuleIOValueTypeEnum.datasetQuote,
targets: []
}
]
};

View File

@@ -1,133 +0,0 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_Switch, Input_Template_UserChatInput } from '../input';
import { Output_Template_Finish, Output_Template_UserChatInput } from '../output';
import { DatasetSearchModeEnum } from '../../../dataset/constants';
export const Dataset_SEARCH_DESC =
'调用“语义检索”和“全文检索”能力,从“知识库”中查找可能与问题相关的参考内容';
export const DatasetSearchModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.datasetSearchNode,
templateType: FlowNodeTemplateTypeEnum.functionCall,
flowType: FlowNodeTypeEnum.datasetSearchNode,
avatar: '/imgs/module/db.png',
name: '知识库搜索',
intro: Dataset_SEARCH_DESC,
showStatus: true,
isTool: true,
inputs: [
Input_Template_Switch,
{
key: ModuleInputKeyEnum.datasetSelectList,
type: FlowNodeInputTypeEnum.selectDataset,
label: 'core.module.input.label.Select dataset',
value: [],
valueType: ModuleIOValueTypeEnum.selectDataset,
list: [],
required: true,
showTargetInApp: false,
showTargetInPlugin: true
},
{
key: ModuleInputKeyEnum.datasetSimilarity,
type: FlowNodeInputTypeEnum.selectDatasetParamsModal,
label: '',
value: 0.4,
valueType: ModuleIOValueTypeEnum.number,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.datasetMaxTokens,
type: FlowNodeInputTypeEnum.hidden,
label: '',
value: 1500,
valueType: ModuleIOValueTypeEnum.number,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.datasetSearchMode,
type: FlowNodeInputTypeEnum.hidden,
label: '',
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: false,
showTargetInPlugin: false,
value: DatasetSearchModeEnum.embedding
},
{
key: ModuleInputKeyEnum.datasetSearchUsingReRank,
type: FlowNodeInputTypeEnum.hidden,
label: '',
valueType: ModuleIOValueTypeEnum.boolean,
showTargetInApp: false,
showTargetInPlugin: false,
value: false
},
{
key: ModuleInputKeyEnum.datasetSearchUsingExtensionQuery,
type: FlowNodeInputTypeEnum.hidden,
label: '',
valueType: ModuleIOValueTypeEnum.boolean,
showTargetInApp: false,
showTargetInPlugin: false,
value: true
},
{
key: ModuleInputKeyEnum.datasetSearchExtensionModel,
type: FlowNodeInputTypeEnum.hidden,
label: '',
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.datasetSearchExtensionBg,
type: FlowNodeInputTypeEnum.hidden,
label: '',
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: false,
showTargetInPlugin: false,
value: ''
},
{
...Input_Template_UserChatInput,
toolDescription: '需要检索的内容'
}
],
outputs: [
Output_Template_UserChatInput,
{
key: ModuleOutputKeyEnum.datasetIsEmpty,
label: 'core.module.output.label.Search result empty',
type: FlowNodeOutputTypeEnum.source,
valueType: ModuleIOValueTypeEnum.boolean,
targets: []
},
{
key: ModuleOutputKeyEnum.datasetUnEmpty,
label: 'core.module.output.label.Search result not empty',
type: FlowNodeOutputTypeEnum.source,
valueType: ModuleIOValueTypeEnum.boolean,
targets: []
},
{
key: ModuleOutputKeyEnum.datasetQuoteQA,
label: 'core.module.Dataset quote.label',
type: FlowNodeOutputTypeEnum.source,
valueType: ModuleIOValueTypeEnum.datasetQuote,
targets: []
}
]
};

View File

@@ -1,128 +0,0 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import {
Input_Template_AddInputParam,
Input_Template_DynamicInput,
Input_Template_Switch
} from '../input';
import { Output_Template_AddOutput, Output_Template_Finish } from '../output';
export const HttpModule468: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.httpRequest468,
templateType: FlowNodeTemplateTypeEnum.externalCall,
flowType: FlowNodeTypeEnum.httpRequest468,
avatar: '/imgs/module/http.png',
name: 'HTTP 请求',
intro: '可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
showStatus: true,
isTool: true,
inputs: [
Input_Template_Switch,
{
key: ModuleInputKeyEnum.httpMethod,
type: FlowNodeInputTypeEnum.custom,
valueType: ModuleIOValueTypeEnum.string,
label: '',
value: 'POST',
required: true,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.httpReqUrl,
type: FlowNodeInputTypeEnum.hidden,
valueType: ModuleIOValueTypeEnum.string,
label: '',
description: 'core.module.input.description.Http Request Url',
placeholder: 'https://api.ai.com/getInventory',
required: false,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.httpHeaders,
type: FlowNodeInputTypeEnum.custom,
valueType: ModuleIOValueTypeEnum.any,
value: [],
label: '',
description: 'core.module.input.description.Http Request Header',
placeholder: 'core.module.input.description.Http Request Header',
required: false,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.httpParams,
type: FlowNodeInputTypeEnum.hidden,
valueType: ModuleIOValueTypeEnum.any,
value: [],
label: '',
required: false,
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.httpJsonBody,
type: FlowNodeInputTypeEnum.hidden,
valueType: ModuleIOValueTypeEnum.any,
value: '',
label: '',
required: false,
showTargetInApp: false,
showTargetInPlugin: false
},
Input_Template_DynamicInput,
{
...Input_Template_AddInputParam,
editField: {
key: true,
description: true,
dataType: true
},
defaultEditField: {
label: '',
key: '',
description: '',
inputType: FlowNodeInputTypeEnum.target,
valueType: ModuleIOValueTypeEnum.string
}
}
],
outputs: [
{
key: ModuleOutputKeyEnum.httpRawResponse,
label: '原始响应',
description: 'HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。',
valueType: ModuleIOValueTypeEnum.any,
type: FlowNodeOutputTypeEnum.source,
targets: []
},
{
...Output_Template_AddOutput,
editField: {
key: true,
description: true,
dataType: true,
defaultValue: true
},
defaultEditField: {
label: '',
key: '',
description: '',
outputType: FlowNodeOutputTypeEnum.source,
valueType: ModuleIOValueTypeEnum.string
}
},
Output_Template_Finish
]
};

View File

@@ -1,86 +0,0 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import {
Input_Template_DynamicInput,
Input_Template_Switch,
Input_Template_AddInputParam
} from '../input';
import { Output_Template_Finish, Output_Template_AddOutput } from '../output';
export const lafModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.lafModule,
templateType: FlowNodeTemplateTypeEnum.externalCall,
flowType: FlowNodeTypeEnum.lafModule,
avatar: '/imgs/module/laf.png',
name: 'Laf 函数调用(测试)',
intro: '可以调用Laf账号下的云函数。',
showStatus: true,
isTool: true,
inputs: [
Input_Template_Switch,
{
key: ModuleInputKeyEnum.httpReqUrl,
type: FlowNodeInputTypeEnum.hidden,
valueType: ModuleIOValueTypeEnum.string,
label: '',
description: 'core.module.input.description.Http Request Url',
placeholder: 'https://api.ai.com/getInventory',
required: false,
showTargetInApp: false,
showTargetInPlugin: false
},
Input_Template_DynamicInput,
{
...Input_Template_AddInputParam,
editField: {
key: true,
description: true,
dataType: true
},
defaultEditField: {
label: '',
key: '',
description: '',
inputType: FlowNodeInputTypeEnum.target,
valueType: ModuleIOValueTypeEnum.string
}
}
],
outputs: [
{
key: ModuleOutputKeyEnum.httpRawResponse,
label: '原始响应',
description: 'HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。',
valueType: ModuleIOValueTypeEnum.any,
type: FlowNodeOutputTypeEnum.source,
targets: []
},
{
...Output_Template_AddOutput,
editField: {
key: true,
description: true,
dataType: true,
defaultValue: true
},
defaultEditField: {
label: '',
key: '',
description: '',
outputType: FlowNodeOutputTypeEnum.source,
valueType: ModuleIOValueTypeEnum.string
}
},
Output_Template_Finish
]
};

View File

@@ -1,43 +0,0 @@
import {
FlowNodeTemplateTypeEnum,
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum
} from '../../constants';
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
export const PluginInputModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.pluginInput,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowType: FlowNodeTypeEnum.pluginInput,
avatar: '/imgs/module/input.png',
name: '定义插件输入',
intro: '自定义配置外部输入,使用插件时,仅暴露自定义配置的输入',
showStatus: false,
inputs: [
{
key: ModuleInputKeyEnum.pluginStart,
type: FlowNodeInputTypeEnum.hidden,
valueType: ModuleIOValueTypeEnum.boolean,
label: '插件开始运行',
description:
'插件开始运行时,会输出一个 True 的标识。有时候,插件不会有额外的的输入,为了顺利的进入下一个阶段,你可以将该值连接到下一个节点的触发器中。',
showTargetInApp: true,
showTargetInPlugin: true
}
],
outputs: [
{
key: ModuleOutputKeyEnum.pluginStart,
label: '插件开始运行',
type: FlowNodeOutputTypeEnum.source,
valueType: ModuleIOValueTypeEnum.boolean,
targets: []
}
]
};

View File

@@ -1,63 +0,0 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import {
Input_Template_History,
Input_Template_Switch,
Input_Template_UserChatInput
} from '../input';
import { Output_Template_Finish, Output_Template_UserChatInput } from '../output';
export const RunAppModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.runApp,
templateType: FlowNodeTemplateTypeEnum.externalCall,
flowType: FlowNodeTypeEnum.runApp,
avatar: '/imgs/module/app.png',
name: '应用调用',
intro: '可以选择一个其他应用进行调用',
showStatus: true,
inputs: [
Input_Template_Switch,
{
key: ModuleInputKeyEnum.runAppSelectApp,
type: FlowNodeInputTypeEnum.selectApp,
valueType: ModuleIOValueTypeEnum.selectApp,
label: '选择一个应用',
description: '选择一个其他应用进行调用',
required: true,
showTargetInApp: false,
showTargetInPlugin: false
},
Input_Template_History,
Input_Template_UserChatInput
],
outputs: [
Output_Template_UserChatInput,
{
key: ModuleOutputKeyEnum.history,
label: '新的上下文',
description: '将该应用回复内容拼接到历史记录中,作为新的上下文返回',
valueType: ModuleIOValueTypeEnum.chatHistory,
type: FlowNodeOutputTypeEnum.source,
targets: []
},
{
key: ModuleOutputKeyEnum.answerText,
label: '回复的文本',
description: '将在应用完全结束后触发',
valueType: ModuleIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.source,
targets: []
},
Output_Template_Finish
]
};

View File

@@ -1,60 +0,0 @@
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
export const UserGuideModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.userGuide,
templateType: FlowNodeTemplateTypeEnum.userGuide,
flowType: FlowNodeTypeEnum.userGuide,
avatar: '/imgs/module/userGuide.png',
name: '系统配置',
intro: '可以配置应用的系统参数。',
inputs: [
{
key: ModuleInputKeyEnum.welcomeText,
type: FlowNodeInputTypeEnum.hidden,
valueType: ModuleIOValueTypeEnum.string,
label: 'core.app.Welcome Text',
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.variables,
type: FlowNodeInputTypeEnum.hidden,
valueType: ModuleIOValueTypeEnum.any,
label: 'core.module.Variable',
value: [],
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.questionGuide,
valueType: ModuleIOValueTypeEnum.boolean,
type: FlowNodeInputTypeEnum.switch,
label: '',
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.tts,
type: FlowNodeInputTypeEnum.hidden,
valueType: ModuleIOValueTypeEnum.any,
label: '',
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.whisper,
type: FlowNodeInputTypeEnum.hidden,
valueType: ModuleIOValueTypeEnum.any,
label: '',
showTargetInApp: false,
showTargetInPlugin: false
}
],
outputs: []
};

View File

@@ -1,40 +0,0 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
export const UserInputModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.questionInput,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowType: FlowNodeTypeEnum.questionInput,
avatar: '/imgs/module/userChatInput.svg',
name: '对话入口',
intro: '当用户发送一个内容后,流程将会从这个模块开始执行。',
inputs: [
{
key: ModuleInputKeyEnum.userChatInput,
type: FlowNodeInputTypeEnum.systemInput,
valueType: ModuleIOValueTypeEnum.string,
label: 'core.module.input.label.user question',
showTargetInApp: false,
showTargetInPlugin: false
}
],
outputs: [
{
key: ModuleOutputKeyEnum.userChatInput,
label: 'core.module.input.label.user question',
type: FlowNodeOutputTypeEnum.source,
valueType: ModuleIOValueTypeEnum.string,
targets: []
}
]
};

View File

@@ -1,107 +0,0 @@
import { FlowNodeTypeEnum } from './node/constant';
import {
ModuleIOValueTypeEnum,
ModuleOutputKeyEnum,
FlowNodeTemplateTypeEnum,
VariableInputEnum
} from './constants';
import { DispatchNodeResponseKeyEnum } from './runtime/constants';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from './node/type';
import { UserModelSchema } from 'support/user/type';
import {
ChatItemType,
ChatItemValueItemType,
ToolRunResponseItemType,
UserChatItemValueItemType
} from '../chat/type';
import { ChatNodeUsageType } from '../../support/wallet/bill/type';
import { RunningModuleItemType } from './runtime/type';
import { PluginTypeEnum } from 'core/plugin/constants';
export type FlowNodeTemplateType = {
id: string; // module id, unique
templateType: `${FlowNodeTemplateTypeEnum}`;
flowType: `${FlowNodeTypeEnum}`; // render node card
avatar?: string;
name: string;
intro: string; // template list intro
isTool?: boolean; // can be connected by tool
showStatus?: boolean; // chatting response step status
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
// plugin data
pluginType?: `${PluginTypeEnum}`;
parentId?: string;
};
export type FlowModuleItemType = FlowNodeTemplateType & {
moduleId: string;
};
export type moduleTemplateListType = {
type: `${FlowNodeTemplateTypeEnum}`;
label: string;
list: FlowNodeTemplateType[];
}[];
// store module type
export type ModuleItemType = {
name: string;
avatar?: string;
intro?: string;
moduleId: string;
position?: {
x: number;
y: number;
};
flowType: `${FlowNodeTypeEnum}`;
showStatus?: boolean;
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
// runTime field
isEntry?: boolean;
};
/* --------------- function type -------------------- */
export type SelectAppItemType = {
id: string;
name: string;
logo: string;
};
/* agent */
export type ClassifyQuestionAgentItemType = {
value: string;
key: string;
};
export type ContextExtractAgentItemType = {
desc: string;
key: string;
required: boolean;
defaultValue?: string;
enum?: string;
};
/* -------------- running module -------------- */
export type ChatDispatchProps = {
res: NextApiResponse;
mode: 'test' | 'chat';
teamId: string;
tmbId: string;
user: UserModelSchema;
appId: string;
chatId?: string;
responseChatItemId?: string;
histories: ChatItemType[];
variables: Record<string, any>;
inputFiles?: UserChatItemValueItemType['file'][];
stream: boolean;
detail: boolean; // response detail
maxRunTimes: number;
};
export type ModuleDispatchProps<T> = ChatDispatchProps & {
module: RunningModuleItemType;
runtimeModules: RunningModuleItemType[];
params: T;
};

View File

@@ -1,123 +0,0 @@
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from './node/constant';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
VariableInputEnum,
variableMap
} from './constants';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from './node/type';
import { ModuleItemType } from './type';
import type { VariableItemType, AppTTSConfigType, AppWhisperConfigType } from '../app/type';
import { Input_Template_Switch } from './template/input';
import { EditorVariablePickerType } from '../../../web/components/common/Textarea/PromptEditor/type';
import { Output_Template_Finish } from './template/output';
import { defaultWhisperConfig } from '../app/constants';
/* module */
export const getGuideModule = (modules: ModuleItemType[]) =>
modules.find((item) => item.flowType === FlowNodeTypeEnum.userGuide);
export const splitGuideModule = (guideModules?: ModuleItemType) => {
const welcomeText: string =
guideModules?.inputs?.find((item) => item.key === ModuleInputKeyEnum.welcomeText)?.value || '';
const variableModules: VariableItemType[] =
guideModules?.inputs.find((item) => item.key === ModuleInputKeyEnum.variables)?.value || [];
const questionGuide: boolean =
!!guideModules?.inputs?.find((item) => item.key === ModuleInputKeyEnum.questionGuide)?.value ||
false;
const ttsConfig: AppTTSConfigType = guideModules?.inputs?.find(
(item) => item.key === ModuleInputKeyEnum.tts
)?.value || { type: 'web' };
const whisperConfig: AppWhisperConfigType =
guideModules?.inputs?.find((item) => item.key === ModuleInputKeyEnum.whisper)?.value ||
defaultWhisperConfig;
return {
welcomeText,
variableModules,
questionGuide,
ttsConfig,
whisperConfig
};
};
export const getOrInitModuleInputValue = (input: FlowNodeInputItemType) => {
if (input.value !== undefined || !input.valueType) return input.value;
const map: Record<string, any> = {
[ModuleIOValueTypeEnum.boolean]: false,
[ModuleIOValueTypeEnum.number]: 0,
[ModuleIOValueTypeEnum.string]: ''
};
return map[input.valueType];
};
export const getModuleInputUiField = (input: FlowNodeInputItemType) => {
if (input.type === FlowNodeInputTypeEnum.input || input.type === FlowNodeInputTypeEnum.textarea) {
return {
placeholder: input.placeholder || input.description
};
}
return {};
};
export const plugin2ModuleIO = (
pluginId: string,
modules: ModuleItemType[]
): {
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
} => {
const pluginInput = modules.find((module) => module.flowType === FlowNodeTypeEnum.pluginInput);
const pluginOutput = modules.find((module) => module.flowType === FlowNodeTypeEnum.pluginOutput);
return {
inputs: pluginInput
? [
{
// plugin id
key: ModuleInputKeyEnum.pluginId,
type: FlowNodeInputTypeEnum.hidden,
label: '',
value: pluginId,
valueType: ModuleIOValueTypeEnum.string,
connected: true,
showTargetInApp: false,
showTargetInPlugin: false
},
// switch
Input_Template_Switch,
...pluginInput.inputs.map((item) => ({
...item,
...getModuleInputUiField(item),
value: getOrInitModuleInputValue(item),
edit: false,
connected: false
}))
]
: [Input_Template_Switch],
outputs: pluginOutput
? [
...pluginOutput.outputs.map((item) => ({
...item,
edit: false
})),
Output_Template_Finish
]
: [Output_Template_Finish]
};
};
export const formatEditorVariablePickerIcon = (
variables: { key: string; label: string; type?: `${VariableInputEnum}` }[]
): EditorVariablePickerType[] => {
return variables.map((item) => ({
...item,
icon: item.type ? variableMap[item.type]?.icon : variableMap['input'].icon
}));
};

View File

@@ -1,31 +1,4 @@
import { ModuleItemType } from '../module/type';
export const defaultModules: ModuleItemType[] = [
{
moduleId: 'custom-output',
name: '自定义输出',
flowType: 'pluginOutput',
showStatus: false,
position: {
x: 994.1266684738011,
y: -45.87689365278443
},
inputs: [],
outputs: []
},
{
moduleId: 'custom-input',
name: '自定义输入',
flowType: 'pluginInput',
showStatus: false,
position: {
x: 457.57860319995154,
y: -44.25099042468186
},
inputs: [],
outputs: []
}
];
import { StoreNodeItemType } from '../workflow/type';
export enum PluginTypeEnum {
folder = 'folder',

View File

@@ -1,4 +1,5 @@
import type { ModuleItemType } from '../module/type.d';
import { StoreEdgeItemType } from 'core/workflow/type/edge';
import type { StoreNodeItemType } from '../workflow/type';
import { PluginTypeEnum } from './constants';
import { HttpAuthMethodType } from './httpPlugin/type';
@@ -6,7 +7,7 @@ export type CreateOnePluginParams = {
name: string;
avatar: string;
intro: string;
modules: ModuleItemType[];
modules: StoreNodeItemType[];
parentId: string | null;
type: `${PluginTypeEnum}`;
metadata?: {
@@ -20,7 +21,8 @@ export type UpdatePluginParams = {
name?: string;
avatar?: string;
intro?: string;
modules?: ModuleItemType[];
modules?: StoreNodeItemType[];
edges?: StoreEdgeItemType[];
metadata?: {
apiSchemaStr?: string;
customHeaders?: string;

View File

@@ -3,15 +3,15 @@ import { OpenApiJsonSchema } from './type';
import yaml from 'js-yaml';
import { OpenAPIV3 } from 'openapi-types';
import { PluginTypeEnum } from '../constants';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from '../../module/node/type';
import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum } from '../../module/node/constant';
import { ModuleIOValueTypeEnum } from '../../module/constants';
import { PluginInputModule } from '../../module/template/system/pluginInput';
import { PluginOutputModule } from '../../module/template/system/pluginOutput';
import { HttpModule468 } from '../../module/template/system/http468';
import { HttpParamAndHeaderItemType } from '../../module/api';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from '../../workflow/type/io.d';
import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum } from '../../workflow/node/constant';
import { NodeInputKeyEnum, WorkflowIOValueTypeEnum } from '../../workflow/constants';
import { PluginInputModule } from '../../workflow/template/system/pluginInput';
import { PluginOutputModule } from '../../workflow/template/system/pluginOutput';
import { HttpModule468 } from '../../workflow/template/system/http468';
import { HttpParamAndHeaderItemType } from '../../workflow/api';
import { CreateOnePluginParams } from '../controller';
import { ModuleItemType } from '../../module/type';
import { StoreNodeItemType } from '../../workflow/type';
import { HttpImgUrl } from '../../../common/file/image/constants';
import SwaggerParser from '@apidevtools/swagger-parser';
@@ -74,6 +74,9 @@ export const httpApiSchema2Plugins = async ({
return jsonSchema.pathData.map((item) => {
const pluginOutputId = getNanoid();
const httpId = getNanoid();
const pluginInputId = getNanoid();
const inputIdMap = new Map();
const pluginOutputKey = 'result';
const properties = item.request?.content?.['application/json']?.schema?.properties;
@@ -83,12 +86,13 @@ export const httpApiSchema2Plugins = async ({
...(item.params?.map((param: any) => {
return {
key: param.name,
valueType: ModuleIOValueTypeEnum.string,
valueType: param.schema.type,
label: param.name,
type: FlowNodeInputTypeEnum.target,
renderTypeList: [FlowNodeInputTypeEnum.reference],
required: param.required,
description: param.description,
edit: true,
toolDescription: param.description,
canEdit: true,
editField: {
key: true,
name: true,
@@ -97,21 +101,20 @@ export const httpApiSchema2Plugins = async ({
dataType: true,
inputType: true,
isToolInput: true
},
connected: true,
toolDescription: param.description
}
};
}) || []),
...(propsKeys?.map((key) => {
const prop = properties[key];
return {
key,
valueType: ModuleIOValueTypeEnum.string,
valueType: prop.type,
label: key,
type: FlowNodeInputTypeEnum.target,
renderTypeList: [FlowNodeInputTypeEnum.reference],
required: false,
description: prop.description,
edit: true,
toolDescription: prop.description,
canEdit: true,
editField: {
key: true,
name: true,
@@ -120,42 +123,33 @@ export const httpApiSchema2Plugins = async ({
dataType: true,
inputType: true,
isToolInput: true
},
connected: true,
toolDescription: prop.description
}
};
}) || [])
];
const pluginOutputs: FlowNodeOutputItemType[] = [
...(item.params?.map((param: any) => {
const id = getNanoid();
inputIdMap.set(param.name, id);
return {
id,
key: param.name,
valueType: ModuleIOValueTypeEnum.string,
valueType: param.schema.type,
label: param.name,
type: FlowNodeOutputTypeEnum.source,
edit: true,
targets: [
{
moduleId: httpId,
key: param.name
}
]
type: FlowNodeOutputTypeEnum.source
};
}) || []),
...(propsKeys?.map((key) => {
const id = getNanoid();
inputIdMap.set(key, id);
return {
id,
key,
valueType: ModuleIOValueTypeEnum.string,
valueType: properties[key].type,
label: key,
type: FlowNodeOutputTypeEnum.source,
edit: true,
targets: [
{
moduleId: httpId,
key
}
]
edit: true
};
}) || [])
];
@@ -164,34 +158,29 @@ export const httpApiSchema2Plugins = async ({
...(item.params?.map((param: any) => {
return {
key: param.name,
valueType: ModuleIOValueTypeEnum.string,
valueType: param.schema.type,
label: param.name,
type: FlowNodeInputTypeEnum.target,
description: param.description,
edit: true,
renderTypeList: [FlowNodeInputTypeEnum.reference],
canEdit: true,
editField: {
key: true,
description: true,
dataType: true
valueType: true
},
connected: true
value: [pluginInputId, inputIdMap.get(param.name)]
};
}) || []),
...(propsKeys?.map((key) => {
const prop = properties[key];
return {
key,
valueType: ModuleIOValueTypeEnum.string,
valueType: properties[key].type,
label: key,
type: FlowNodeInputTypeEnum.target,
description: prop.description,
edit: true,
renderTypeList: [FlowNodeInputTypeEnum.reference],
canEdit: true,
editField: {
key: true,
description: true,
dataType: true
valueType: true
},
connected: true
value: [pluginInputId, inputIdMap.get(key)]
};
}) || [])
];
@@ -207,7 +196,7 @@ export const httpApiSchema2Plugins = async ({
if (param.in === 'header') {
httpNodeHeaders.push({
key: param.name,
type: param.schema?.type || ModuleIOValueTypeEnum.string,
type: param.schema?.type || WorkflowIOValueTypeEnum.string,
value: `{{${param.name}}}`
});
} else if (param.in === 'body') {
@@ -219,7 +208,7 @@ export const httpApiSchema2Plugins = async ({
} else if (param.in === 'query') {
httpNodeParams.push({
key: param.name,
type: param.schema?.type || ModuleIOValueTypeEnum.string,
type: param.schema?.type || WorkflowIOValueTypeEnum.string,
value: `{{${param.name}}}`
});
}
@@ -250,7 +239,7 @@ export const httpApiSchema2Plugins = async ({
for (const key in headersObj) {
httpNodeHeaders.push({
key,
type: 'string',
type: WorkflowIOValueTypeEnum.string,
// @ts-ignore
value: headersObj[key]
});
@@ -258,57 +247,27 @@ export const httpApiSchema2Plugins = async ({
}
/* Combine complete modules */
const modules: ModuleItemType[] = [
const modules: StoreNodeItemType[] = [
{
moduleId: getNanoid(),
nodeId: pluginInputId,
name: PluginInputModule.name,
intro: PluginInputModule.intro,
avatar: PluginInputModule.avatar,
flowType: PluginInputModule.flowType,
flowNodeType: PluginInputModule.flowNodeType,
showStatus: PluginInputModule.showStatus,
position: {
x: 616.4226348688949,
y: -165.05298493910115
},
inputs: [
{
key: 'pluginStart',
type: 'hidden',
valueType: 'boolean',
label: '插件开始运行',
description:
'插件开始运行时,会输出一个 True 的标识。有时候,插件不会有额外的的输入,为了顺利的进入下一个阶段,你可以将该值连接到下一个节点的触发器中。',
showTargetInApp: true,
showTargetInPlugin: true,
connected: true
},
...pluginInputs
],
outputs: [
{
key: 'pluginStart',
label: '插件开始运行',
type: 'source',
valueType: 'boolean',
targets:
pluginOutputs.length === 0
? [
{
moduleId: httpId,
key: 'switch'
}
]
: []
},
...pluginOutputs
]
inputs: pluginInputs,
outputs: pluginOutputs
},
{
moduleId: pluginOutputId,
nodeId: pluginOutputId,
name: PluginOutputModule.name,
intro: PluginOutputModule.intro,
avatar: PluginOutputModule.avatar,
flowType: PluginOutputModule.flowType,
flowNodeType: PluginOutputModule.flowNodeType,
showStatus: PluginOutputModule.showStatus,
position: {
x: 1607.7142331269126,
@@ -317,40 +276,36 @@ export const httpApiSchema2Plugins = async ({
inputs: [
{
key: pluginOutputKey,
valueType: 'string',
valueType: WorkflowIOValueTypeEnum.string,
label: pluginOutputKey,
type: 'target',
required: true,
renderTypeList: [FlowNodeInputTypeEnum.reference],
required: false,
description: '',
edit: true,
canEdit: true,
editField: {
key: true,
name: true,
description: true,
required: false,
dataType: true,
inputType: false
valueType: true
},
connected: true
value: [httpId, 'httpRawResponse']
}
],
outputs: [
{
id: pluginOutputId,
key: pluginOutputKey,
valueType: 'string',
valueType: WorkflowIOValueTypeEnum.string,
label: pluginOutputKey,
type: 'source',
edit: true,
targets: []
type: FlowNodeOutputTypeEnum.static
}
]
},
{
moduleId: httpId,
nodeId: httpId,
name: HttpModule468.name,
intro: HttpModule468.intro,
avatar: HttpModule468.avatar,
flowType: HttpModule468.flowType,
flowNodeType: HttpModule468.flowNodeType,
showStatus: true,
position: {
x: 1042.549746602742,
@@ -358,153 +313,79 @@ export const httpApiSchema2Plugins = async ({
},
inputs: [
{
key: 'switch',
type: 'target',
label: 'core.module.input.label.switch',
description: 'core.module.input.description.Trigger',
valueType: 'any',
showTargetInApp: true,
showTargetInPlugin: true,
connected: false
key: NodeInputKeyEnum.addInputParam,
renderTypeList: [FlowNodeInputTypeEnum.addInputParam],
valueType: WorkflowIOValueTypeEnum.dynamic,
label: '',
required: false,
description: 'core.module.input.description.HTTP Dynamic Input',
editField: {
key: true,
valueType: true
}
},
...httpInputs,
{
key: 'system_httpMethod',
type: 'custom',
valueType: 'string',
renderTypeList: [FlowNodeInputTypeEnum.custom],
valueType: WorkflowIOValueTypeEnum.string,
label: '',
value: item.method.toUpperCase(),
required: true,
showTargetInApp: false,
showTargetInPlugin: false,
connected: false
required: true
},
{
key: 'system_httpReqUrl',
type: 'hidden',
valueType: 'string',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.string,
label: '',
description: 'core.module.input.description.Http Request Url',
placeholder: 'https://api.ai.com/getInventory',
required: false,
showTargetInApp: false,
showTargetInPlugin: false,
value: requestUrl,
connected: false
value: requestUrl
},
{
key: 'system_httpHeader',
type: 'custom',
valueType: 'any',
renderTypeList: [FlowNodeInputTypeEnum.custom],
valueType: WorkflowIOValueTypeEnum.any,
value: httpNodeHeaders,
label: '',
description: 'core.module.input.description.Http Request Header',
placeholder: 'core.module.input.description.Http Request Header',
required: false,
showTargetInApp: false,
showTargetInPlugin: false,
connected: false
required: false
},
{
key: 'system_httpParams',
type: 'hidden',
valueType: 'any',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
value: httpNodeParams,
label: '',
required: false,
showTargetInApp: false,
showTargetInPlugin: false,
connected: false
required: false
},
{
key: 'system_httpJsonBody',
type: 'hidden',
valueType: 'any',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
value: httpNodeBody,
label: '',
required: false,
showTargetInApp: false,
showTargetInPlugin: false,
connected: false
},
{
key: 'DYNAMIC_INPUT_KEY',
type: 'target',
valueType: 'any',
label: 'core.module.inputType.dynamicTargetInput',
description: 'core.module.input.description.dynamic input',
required: false,
showTargetInApp: false,
showTargetInPlugin: true,
hideInApp: true,
connected: false
},
{
key: 'system_addInputParam',
type: 'addInputParam',
valueType: 'any',
label: '',
required: false,
showTargetInApp: false,
showTargetInPlugin: false,
editField: {
key: true,
description: true,
dataType: true
},
defaultEditField: {
label: '',
key: '',
description: '',
inputType: 'target',
valueType: 'string'
},
connected: false
},
...httpInputs
],
outputs: [
{
key: 'finish',
label: 'core.module.output.label.running done',
description: 'core.module.output.description.running done',
valueType: 'boolean',
type: 'source',
targets: []
},
{
key: 'httpRawResponse',
label: '原始响应',
description: 'HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。',
valueType: 'any',
type: 'source',
targets: [
{
moduleId: pluginOutputId,
key: pluginOutputKey
}
]
},
{
key: 'system_addOutputParam',
type: 'addOutputParam',
valueType: 'any',
label: '',
targets: [],
editField: {
key: true,
description: true,
dataType: true,
defaultValue: true
},
defaultEditField: {
label: '',
key: '',
description: '',
outputType: 'source',
valueType: 'string'
}
required: false
}
]
],
outputs: HttpModule468.outputs
}
];
const edges = [
{
source: pluginInputId,
target: httpId,
sourcePort: `${pluginInputId}-source-right`,
targetPort: `${httpId}-target-left`
},
{
source: httpId,
target: pluginOutputId,
sourcePort: `${httpId}-source-right`,
targetPort: `${pluginOutputId}-target-left`
}
];
@@ -514,7 +395,8 @@ export const httpApiSchema2Plugins = async ({
intro: item.description,
parentId,
type: PluginTypeEnum.http,
modules
modules,
edges
};
});
};

View File

@@ -1,5 +1,6 @@
import { ModuleTemplateTypeEnum } from 'core/module/constants';
import type { FlowModuleTemplateType, ModuleItemType } from '../module/type.d';
import { StoreEdgeItemType } from 'core/workflow/type/edge';
import { ModuleTemplateTypeEnum } from '../workflow/constants';
import type { FlowModuleTemplateType, StoreNodeItemType } from '../workflow/type';
import { PluginSourceEnum, PluginTypeEnum } from './constants';
import { MethodType } from './controller';
@@ -12,7 +13,8 @@ export type PluginItemSchema = {
avatar: string;
intro: string;
updateTime: Date;
modules: ModuleItemType[];
modules: StoreNodeItemType[];
edges: StoreEdgeItemType[];
parentId: string;
type: `${PluginTypeEnum}`;
metadata?: {
@@ -20,6 +22,7 @@ export type PluginItemSchema = {
apiSchemaStr?: string;
customHeaders?: string;
};
version?: 'v1' | 'v2';
};
/* plugin template */
@@ -29,7 +32,6 @@ export type PluginTemplateType = PluginRuntimeType & {
source: `${PluginSourceEnum}`;
templateType: FlowNodeTemplateType['templateType'];
intro: string;
modules: ModuleItemType[];
};
export type PluginRuntimeType = {
@@ -38,5 +40,6 @@ export type PluginRuntimeType = {
avatar: string;
showStatus?: boolean;
isTool?: boolean;
modules: ModuleItemType[];
nodes: StoreNodeItemType[];
edges: StoreEdgeItemType[];
};

View File

@@ -1,10 +1,10 @@
import { VectorModelItemType } from '../ai/model.d';
import { DYNAMIC_INPUT_KEY } from './constants';
import { NodeInputKeyEnum } from './constants';
export type SelectedDatasetType = { datasetId: string; vectorModel: VectorModelItemType }[];
export type HttpBodyType<T = any> = {
[DYNAMIC_INPUT_KEY]: Record<string, any>;
export type HttpBodyType<T = Record<string, any>> = {
[NodeInputKeyEnum.addInputParam]: Record<string, any>;
} & T;
export type HttpQueryType = {
appId: string;

View File

@@ -1,5 +1,4 @@
export enum FlowNodeTemplateTypeEnum {
userGuide = 'userGuide',
systemInput = 'systemInput',
tools = 'tools',
textAnswer = 'textAnswer',
@@ -11,13 +10,15 @@ export enum FlowNodeTemplateTypeEnum {
other = 'other'
}
export enum ModuleIOValueTypeEnum {
export enum WorkflowIOValueTypeEnum {
string = 'string',
number = 'number',
boolean = 'boolean',
any = 'any',
chatHistory = 'chatHistory',
datasetQuote = 'datasetQuote',
any = 'any',
dynamic = 'dynamic',
// plugin special type
selectApp = 'selectApp',
@@ -28,17 +29,21 @@ export enum ModuleIOValueTypeEnum {
}
/* reg: modulename key */
export enum ModuleInputKeyEnum {
export enum NodeInputKeyEnum {
// old
welcomeText = 'welcomeText',
variables = 'variables',
switch = 'switch', // a trigger switch
history = 'history',
userChatInput = 'userChatInput',
answerText = 'text',
// system config
questionGuide = 'questionGuide',
tts = 'tts',
whisper = 'whisper',
answerText = 'text',
variables = 'variables',
scheduleTrigger = 'scheduleTrigger',
agents = 'agents', // cq agent key
// latest
@@ -89,13 +94,16 @@ export enum ModuleInputKeyEnum {
// plugin
pluginId = 'pluginId',
pluginStart = 'pluginStart'
pluginStart = 'pluginStart',
// if else
condition = 'condition',
ifElseList = 'ifElseList'
}
export enum ModuleOutputKeyEnum {
export enum NodeOutputKeyEnum {
// common
userChatInput = 'userChatInput',
finish = 'finish',
history = 'history',
answerText = 'answerText', // module answer. the value will be show and save to history
success = 'success',
@@ -104,10 +112,10 @@ export enum ModuleOutputKeyEnum {
addOutputParam = 'system_addOutputParam',
// dataset
datasetIsEmpty = 'isEmpty',
datasetUnEmpty = 'unEmpty',
datasetQuoteQA = 'quoteQA',
// classify
cqResult = 'cqResult',
// context extract
contextExtractFields = 'fields',
@@ -122,7 +130,10 @@ export enum ModuleOutputKeyEnum {
httpRawResponse = 'httpRawResponse',
// plugin
pluginStart = 'pluginStart'
pluginStart = 'pluginStart',
if = 'IF',
else = 'ELSE'
}
export enum VariableInputEnum {
@@ -154,4 +165,11 @@ export const variableMap = {
}
};
export const DYNAMIC_INPUT_KEY = 'DYNAMIC_INPUT_KEY';
export const DYNAMIC_INPUT_REFERENCE_KEY = 'DYNAMIC_INPUT_REFERENCE_KEY';
/* run time */
export enum RuntimeEdgeStatusEnum {
'waiting' = 'waiting',
'active' = 'active',
'skipped' = 'skipped'
}

View File

@@ -0,0 +1,118 @@
export enum FlowNodeInputTypeEnum { // render ui
reference = 'reference', // reference to other node output
input = 'input', // one line input
numberInput = 'numberInput',
switch = 'switch', // true/false
// editor
textarea = 'textarea',
JSONEditor = 'JSONEditor',
addInputParam = 'addInputParam', // params input
// special input
selectApp = 'selectApp',
// ai model select
selectLLMModel = 'selectLLMModel',
settingLLMModel = 'settingLLMModel',
// dataset special input
selectDataset = 'selectDataset',
selectDatasetParamsModal = 'selectDatasetParamsModal',
settingDatasetQuotePrompt = 'settingDatasetQuotePrompt',
select = 'select',
hidden = 'hidden',
custom = 'custom'
}
export const FlowNodeInputMap: Record<
FlowNodeInputTypeEnum,
{
icon: string;
}
> = {
[FlowNodeInputTypeEnum.reference]: {
icon: 'core/workflow/inputType/reference'
},
[FlowNodeInputTypeEnum.input]: {
icon: 'core/workflow/inputType/input'
},
[FlowNodeInputTypeEnum.numberInput]: {
icon: 'core/workflow/inputType/numberInput'
},
[FlowNodeInputTypeEnum.select]: {
icon: 'core/workflow/inputType/input'
},
[FlowNodeInputTypeEnum.switch]: {
icon: 'core/workflow/inputType/switch'
},
[FlowNodeInputTypeEnum.textarea]: {
icon: 'core/workflow/inputType/textarea'
},
[FlowNodeInputTypeEnum.JSONEditor]: {
icon: 'core/workflow/inputType/jsonEditor'
},
[FlowNodeInputTypeEnum.addInputParam]: {
icon: 'core/workflow/inputType/dynamic'
},
[FlowNodeInputTypeEnum.selectApp]: {
icon: 'core/workflow/inputType/selectApp'
},
[FlowNodeInputTypeEnum.selectLLMModel]: {
icon: 'core/workflow/inputType/selectLLM'
},
[FlowNodeInputTypeEnum.settingLLMModel]: {
icon: 'core/workflow/inputType/selectLLM'
},
[FlowNodeInputTypeEnum.selectDataset]: {
icon: 'core/workflow/inputType/selectDataset'
},
[FlowNodeInputTypeEnum.selectDatasetParamsModal]: {
icon: 'core/workflow/inputType/selectDataset'
},
[FlowNodeInputTypeEnum.settingDatasetQuotePrompt]: {
icon: 'core/workflow/inputType/selectDataset'
},
[FlowNodeInputTypeEnum.hidden]: {
icon: 'core/workflow/inputType/select'
},
[FlowNodeInputTypeEnum.custom]: {
icon: 'core/workflow/inputType/select'
}
};
export enum FlowNodeOutputTypeEnum {
hidden = 'hidden',
source = 'source',
static = 'static',
dynamic = 'dynamic'
}
export enum FlowNodeTypeEnum {
emptyNode = 'emptyNode',
systemConfig = 'userGuide',
globalVariable = 'globalVariable',
workflowStart = 'workflowStart',
chatNode = 'chatNode',
datasetSearchNode = 'datasetSearchNode',
datasetConcatNode = 'datasetConcatNode',
answerNode = 'answerNode',
classifyQuestion = 'classifyQuestion',
contentExtract = 'contentExtract',
httpRequest468 = 'httpRequest468',
runApp = 'app',
pluginModule = 'pluginModule',
pluginInput = 'pluginInput',
pluginOutput = 'pluginOutput',
queryExtension = 'cfr',
tools = 'tools',
stopTool = 'stopTool',
lafModule = 'lafModule',
ifElseNode = 'ifElseNode'
}
export const EDGE_TYPE = 'default';

View File

@@ -0,0 +1,39 @@
/*
react flow type
*/
import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from './constant';
import { WorkflowIOValueTypeEnum, NodeInputKeyEnum, NodeOutputKeyEnum } from '../constants';
import { SelectedDatasetType } from '../api';
import { LLMModelTypeEnum } from '../../ai/constants';
/* --------------- edit field ------------------- */
export type EditInputFieldMapType = EditOutputFieldMapType & {
inputType?: boolean;
};
export type EditOutputFieldMapType = {
key?: boolean;
description?: boolean;
valueType?: boolean; // output
required?: boolean;
defaultValue?: boolean;
};
export type EditNodeFieldType = {
inputType?: FlowNodeInputTypeEnum; // input type
valueType?: WorkflowIOValueTypeEnum;
required?: boolean;
key?: string;
label?: string;
description?: string;
isToolInput?: boolean;
defaultValue?: string;
maxLength?: number;
max?: number;
min?: number;
editField?: EditInputFieldMapType;
dynamicParamDefaultValue?: {
inputType?: FlowNodeInputTypeEnum; // input type
valueType?: WorkflowIOValueTypeEnum;
required?: boolean;
};
};

View File

@@ -1,3 +1,5 @@
import { FlowNodeInputTypeEnum } from '../node/constant';
export enum SseResponseEventEnum {
error = 'error',
answer = 'answer', // animation stream
@@ -11,9 +13,17 @@ export enum SseResponseEventEnum {
}
export enum DispatchNodeResponseKeyEnum {
skipHandleId = 'skipHandleId', // skip handle id
nodeResponse = 'responseData', // run node response
nodeDispatchUsages = 'nodeDispatchUsages', // the node bill.
childrenResponses = 'childrenResponses', // Some nodes make recursive calls that need to be returned
toolResponses = 'toolResponses', // The result is passed back to the tool node for use
assistantResponses = 'assistantResponses' // assistant response
}
export const needReplaceReferenceInputTypeList = [
FlowNodeInputTypeEnum.reference,
FlowNodeInputTypeEnum.settingDatasetQuotePrompt,
FlowNodeInputTypeEnum.addInputParam,
FlowNodeInputTypeEnum.custom
] as string[];

View File

@@ -1,38 +1,28 @@
import { ChatNodeUsageType } from '../../../support/wallet/bill/type';
import { ChatItemValueItemType, ToolRunResponseItemType } from '../../chat/type';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from '../node/type';
import { ModuleItemType } from '../type';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from '../type/io.d';
import { StoreNodeItemType } from '../type';
import { DispatchNodeResponseKeyEnum } from './constants';
import { StoreEdgeItemType } from '../type/edge';
import { NodeInputKeyEnum } from '../constants';
export type RunningModuleItemType = {
name: ModuleItemType['name'];
avatar: ModuleItemType['avatar'];
intro?: ModuleItemType['intro'];
moduleId: ModuleItemType['moduleId'];
flowType: ModuleItemType['flowType'];
showStatus?: ModuleItemType['showStatus'];
isEntry?: ModuleItemType['isEntry'];
export type RuntimeNodeItemType = {
nodeId: StoreNodeItemType['nodeId'];
name: StoreNodeItemType['name'];
avatar: StoreNodeItemType['avatar'];
intro?: StoreNodeItemType['intro'];
flowNodeType: StoreNodeItemType['flowNodeType'];
showStatus?: StoreNodeItemType['showStatus'];
isEntry?: StoreNodeItemType['isEntry'];
inputs: {
key: string;
value?: any;
valueType?: FlowNodeInputItemType['valueType'];
required?: boolean;
toolDescription?: string;
}[];
outputs: {
key: string;
required?: boolean;
defaultValue?: any;
answer?: boolean;
response?: boolean;
value?: any;
valueType?: FlowNodeOutputItemType['valueType'];
targets: {
moduleId: string;
key: string;
}[];
}[];
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
pluginId?: string;
};
export type RuntimeEdgeItemType = StoreEdgeItemType & {
status: 'waiting' | 'active' | 'skipped';
};
export type DispatchNodeResponseType = {
@@ -84,8 +74,8 @@ export type DispatchNodeResponseType = {
pluginOutput?: Record<string, any>;
pluginDetail?: ChatHistoryItemResType[];
// tf switch
tfSwitchResult?: boolean;
// if-else
ifElseResult?: 'IF' | 'ELSE';
// tool
toolCallTokens?: number;
@@ -94,9 +84,21 @@ 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[];
} & T;
/* Single node props */
export type AIChatNodeProps = {
[NodeInputKeyEnum.aiModel]: string;
[NodeInputKeyEnum.aiSystemPrompt]?: string;
[NodeInputKeyEnum.aiChatTemperature]: number;
[NodeInputKeyEnum.aiChatMaxToken]: number;
[NodeInputKeyEnum.aiChatIsResponseText]: boolean;
[NodeInputKeyEnum.aiChatQuoteTemplate]?: string;
[NodeInputKeyEnum.aiChatQuotePrompt]?: string;
};

View File

@@ -0,0 +1,199 @@
import { ChatCompletionRequestMessageRoleEnum } from '../../ai/constants';
import { NodeOutputKeyEnum } from '../constants';
import { FlowNodeTypeEnum } from '../node/constant';
import { StoreNodeItemType } from '../type';
import { StoreEdgeItemType } from '../type/edge';
import { RuntimeEdgeItemType, RuntimeNodeItemType } from './type';
import { VARIABLE_NODE_ID } from '../../../../../projects/app/src/web/core/workflow/constants/index';
export const initWorkflowEdgeStatus = (edges: StoreEdgeItemType[]): RuntimeEdgeItemType[] => {
return (
edges?.map((edge) => ({
...edge,
status: 'waiting'
})) || []
);
};
export const getDefaultEntryNodeIds = (nodes: (StoreNodeItemType | RuntimeNodeItemType)[]) => {
const entryList = [
FlowNodeTypeEnum.systemConfig,
FlowNodeTypeEnum.workflowStart,
FlowNodeTypeEnum.pluginInput
];
return nodes
.filter((node) => entryList.includes(node.flowNodeType as any))
.map((item) => item.nodeId);
};
export const storeNodes2RuntimeNodes = (
nodes: StoreNodeItemType[],
entryNodeIds: string[]
): RuntimeNodeItemType[] => {
return (
nodes.map<RuntimeNodeItemType>((node) => {
return {
nodeId: node.nodeId,
name: node.name,
avatar: node.avatar,
intro: node.intro,
flowNodeType: node.flowNodeType,
showStatus: node.showStatus,
isEntry: entryNodeIds.includes(node.nodeId),
inputs: node.inputs,
outputs: node.outputs,
pluginId: node.pluginId
};
}) || []
);
};
export const filterWorkflowEdges = (edges: RuntimeEdgeItemType[]) => {
return edges.filter(
(edge) =>
edge.sourceHandle !== NodeOutputKeyEnum.selectedTools &&
edge.targetHandle !== NodeOutputKeyEnum.selectedTools
);
};
/*
区分普通连线和递归连线
递归连线:可以通过往上查询 nodes最终追溯到自身
*/
export const splitEdges2WorkflowEdges = ({
edges,
allEdges,
currentNode
}: {
edges: RuntimeEdgeItemType[];
allEdges: RuntimeEdgeItemType[];
currentNode: RuntimeNodeItemType;
}) => {
const commonEdges: RuntimeEdgeItemType[] = [];
const recursiveEdges: RuntimeEdgeItemType[] = [];
edges.forEach((edge) => {
const checkIsCurrentNode = (edge: RuntimeEdgeItemType): boolean => {
const sourceEdge = allEdges.find((item) => item.target === edge.source);
if (!sourceEdge) return false;
if (sourceEdge.source === currentNode.nodeId) return true;
return checkIsCurrentNode(sourceEdge);
};
if (checkIsCurrentNode(edge)) {
recursiveEdges.push(edge);
} else {
commonEdges.push(edge);
}
});
return { commonEdges, recursiveEdges };
};
/*
1. 输入线分类:普通线和递归线(可以追溯到自身)
2. 起始线全部非 waiting 执行,或递归线全部非 waiting 执行
*/
export const checkNodeRunStatus = ({
node,
runtimeEdges
}: {
node: RuntimeNodeItemType;
runtimeEdges: RuntimeEdgeItemType[];
}) => {
const workflowEdges = filterWorkflowEdges(runtimeEdges).filter(
(item) => item.target === node.nodeId
);
if (workflowEdges.length === 0) {
return 'run';
}
const { commonEdges, recursiveEdges } = splitEdges2WorkflowEdges({
edges: workflowEdges,
allEdges: runtimeEdges,
currentNode: node
});
// check skip
if (commonEdges.every((item) => item.status === 'skipped')) {
return 'skip';
}
if (recursiveEdges.length > 0 && recursiveEdges.every((item) => item.status === 'skipped')) {
return 'skip';
}
// check active
if (commonEdges.every((item) => item.status !== 'waiting')) {
return 'run';
}
if (recursiveEdges.length > 0 && recursiveEdges.every((item) => item.status !== 'waiting')) {
return 'run';
}
return 'wait';
};
export const getReferenceVariableValue = ({
value,
nodes,
variables
}: {
value: [string, string];
nodes: RuntimeNodeItemType[];
variables: Record<string, any>;
}) => {
if (
!Array.isArray(value) ||
value.length !== 2 ||
typeof value[0] !== 'string' ||
typeof value[1] !== 'string'
) {
return value;
}
const sourceNodeId = value[0];
const outputId = value[1];
if (sourceNodeId === VARIABLE_NODE_ID && outputId) {
return variables[outputId];
}
const node = nodes.find((node) => node.nodeId === sourceNodeId);
if (!node) {
return undefined;
}
const outputValue = node.outputs.find((output) => output.id === outputId)?.value;
return outputValue;
};
export const textAdaptGptResponse = ({
text,
model = '',
finish_reason = null,
extraData = {}
}: {
model?: string;
text: string | null;
finish_reason?: null | 'stop';
extraData?: Object;
}) => {
return JSON.stringify({
...extraData,
id: '',
object: '',
created: 0,
model,
choices: [
{
delta:
text === null
? {}
: { role: ChatCompletionRequestMessageRoleEnum.Assistant, content: text },
index: 0,
finish_reason
}
]
});
};

View File

@@ -1,5 +1,6 @@
import { UserGuideModule } from './system/userGuide';
import { UserInputModule } from './system/userInput';
import { SystemConfigNode } from './system/systemConfig';
import { EmptyNode } from './system/emptyNode';
import { WorkflowStart } from './system/workflowStart';
import { AiChatModule } from './system/aiChat';
import { DatasetSearchModule } from './system/datasetSearch';
import { DatasetConcatModule } from './system/datasetConcat';
@@ -7,7 +8,6 @@ import { AssignedAnswerModule } from './system/assignedAnswer';
import { ClassifyQuestionModule } from './system/classifyQuestion';
import { ContextExtractModule } from './system/contextExtract';
import { HttpModule468 } from './system/http468';
import { HttpModule } from './system/abandon/http';
import { ToolModule } from './system/tools';
import { StopToolNode } from './system/stopTool';
@@ -18,14 +18,15 @@ import { PluginOutputModule } from './system/pluginOutput';
import { RunPluginModule } from './system/runPlugin';
import { AiQueryExtension } from './system/queryExtension';
import type { FlowNodeTemplateType, moduleTemplateListType } from '../../module/type.d';
import { FlowNodeTemplateTypeEnum } from '../../module/constants';
import type { FlowNodeTemplateType, nodeTemplateListType } from '../type';
import { FlowNodeTemplateTypeEnum } from '../../workflow/constants';
import { lafModule } from './system/laf';
import { ifElseNode } from './system/ifElse/index';
/* app flow module templates */
export const appSystemModuleTemplates: FlowNodeTemplateType[] = [
UserGuideModule,
UserInputModule,
SystemConfigNode,
WorkflowStart,
AiChatModule,
AssignedAnswerModule,
DatasetSearchModule,
@@ -37,7 +38,8 @@ export const appSystemModuleTemplates: FlowNodeTemplateType[] = [
ContextExtractModule,
HttpModule468,
AiQueryExtension,
lafModule
lafModule,
ifElseNode
];
/* plugin flow module templates */
export const pluginSystemModuleTemplates: FlowNodeTemplateType[] = [
@@ -54,13 +56,15 @@ export const pluginSystemModuleTemplates: FlowNodeTemplateType[] = [
ContextExtractModule,
HttpModule468,
AiQueryExtension,
lafModule
lafModule,
ifElseNode
];
/* all module */
export const moduleTemplatesFlat: FlowNodeTemplateType[] = [
UserGuideModule,
UserInputModule,
EmptyNode,
SystemConfigNode,
WorkflowStart,
AiChatModule,
DatasetSearchModule,
DatasetConcatModule,
@@ -68,7 +72,6 @@ export const moduleTemplatesFlat: FlowNodeTemplateType[] = [
ClassifyQuestionModule,
ContextExtractModule,
HttpModule468,
HttpModule,
ToolModule,
StopToolNode,
AiChatModule,
@@ -77,13 +80,14 @@ export const moduleTemplatesFlat: FlowNodeTemplateType[] = [
PluginOutputModule,
RunPluginModule,
AiQueryExtension,
lafModule
lafModule,
ifElseNode
];
export const moduleTemplatesList: moduleTemplateListType = [
export const moduleTemplatesList: nodeTemplateListType = [
{
type: FlowNodeTemplateTypeEnum.userGuide,
label: '',
type: FlowNodeTemplateTypeEnum.systemInput,
label: 'core.module.template.System input module',
list: []
},
{
@@ -115,10 +119,5 @@ export const moduleTemplatesList: moduleTemplateListType = [
type: FlowNodeTemplateTypeEnum.other,
label: '其他',
list: []
},
{
type: FlowNodeTemplateTypeEnum.systemInput,
label: 'core.module.template.System input module',
list: []
}
];

View File

@@ -0,0 +1,65 @@
import { NodeInputKeyEnum } from '../constants';
import { FlowNodeInputTypeEnum } from '../node/constant';
import { WorkflowIOValueTypeEnum } from '../constants';
import { chatNodeSystemPromptTip } from './tip';
import { FlowNodeInputItemType } from '../type/io';
export const Input_Template_History: FlowNodeInputItemType = {
key: NodeInputKeyEnum.history,
renderTypeList: [FlowNodeInputTypeEnum.numberInput, FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.chatHistory,
label: 'core.module.input.label.chat history',
required: true,
min: 0,
max: 30,
value: 6
};
export const Input_Template_UserChatInput: FlowNodeInputItemType = {
key: NodeInputKeyEnum.userChatInput,
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.textarea],
valueType: WorkflowIOValueTypeEnum.string,
label: '用户问题',
required: true
};
export const Input_Template_DynamicInput: FlowNodeInputItemType = {
key: NodeInputKeyEnum.addInputParam,
renderTypeList: [FlowNodeInputTypeEnum.addInputParam],
valueType: WorkflowIOValueTypeEnum.dynamic,
label: '',
required: false
};
export const Input_Template_SelectAIModel: FlowNodeInputItemType = {
key: NodeInputKeyEnum.aiModel,
renderTypeList: [FlowNodeInputTypeEnum.selectLLMModel, FlowNodeInputTypeEnum.reference],
label: 'core.module.input.label.aiModel',
required: true,
valueType: WorkflowIOValueTypeEnum.string
};
export const Input_Template_SettingAiModel: FlowNodeInputItemType = {
key: NodeInputKeyEnum.aiModel,
renderTypeList: [FlowNodeInputTypeEnum.settingLLMModel, FlowNodeInputTypeEnum.reference],
label: 'core.module.input.label.aiModel',
valueType: WorkflowIOValueTypeEnum.string
};
export const Input_Template_System_Prompt: FlowNodeInputItemType = {
key: NodeInputKeyEnum.aiSystemPrompt,
renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference],
max: 3000,
valueType: WorkflowIOValueTypeEnum.string,
label: 'core.ai.Prompt',
description: chatNodeSystemPromptTip,
placeholder: chatNodeSystemPromptTip
};
export const Input_Template_Dataset_Quote: FlowNodeInputItemType = {
key: NodeInputKeyEnum.aiChatDatasetQuote,
renderTypeList: [FlowNodeInputTypeEnum.settingDatasetQuotePrompt],
label: '',
debugLabel: '知识库引用',
description: '',
valueType: WorkflowIOValueTypeEnum.datasetQuote
};

View File

@@ -0,0 +1,17 @@
import type { FlowNodeOutputItemType } from '../type/io.d';
import { NodeOutputKeyEnum } from '../constants';
import { FlowNodeOutputTypeEnum } from '../node/constant';
import { WorkflowIOValueTypeEnum } from '../constants';
export const Output_Template_AddOutput: FlowNodeOutputItemType = {
id: NodeOutputKeyEnum.addOutputParam,
key: NodeOutputKeyEnum.addOutputParam,
type: FlowNodeOutputTypeEnum.dynamic,
valueType: WorkflowIOValueTypeEnum.dynamic,
label: '',
editField: {
key: true,
valueType: true
}
};

View File

@@ -0,0 +1,105 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import {
Input_Template_SettingAiModel,
Input_Template_Dataset_Quote,
Input_Template_History,
Input_Template_System_Prompt,
Input_Template_UserChatInput
} from '../input';
import { chatNodeSystemPromptTip } from '../tip';
import { getHandleConfig } from '../utils';
export const AiChatModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.chatNode,
templateType: FlowNodeTemplateTypeEnum.textAnswer,
flowNodeType: FlowNodeTypeEnum.chatNode,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/AI.png',
name: 'AI 对话',
intro: 'AI 大模型对话',
showStatus: true,
isTool: true,
inputs: [
Input_Template_SettingAiModel,
// --- settings modal
{
key: NodeInputKeyEnum.aiChatTemperature,
renderTypeList: [FlowNodeInputTypeEnum.hidden], // Set in the pop-up window
label: '',
value: 0,
valueType: WorkflowIOValueTypeEnum.number,
min: 0,
max: 10,
step: 1
},
{
key: NodeInputKeyEnum.aiChatMaxToken,
renderTypeList: [FlowNodeInputTypeEnum.hidden], // Set in the pop-up window
label: '',
value: 2000,
valueType: WorkflowIOValueTypeEnum.number,
min: 100,
max: 4000,
step: 50
},
{
key: NodeInputKeyEnum.aiChatIsResponseText,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
value: true,
valueType: WorkflowIOValueTypeEnum.boolean
},
{
key: NodeInputKeyEnum.aiChatQuoteTemplate,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
},
{
key: NodeInputKeyEnum.aiChatQuotePrompt,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
},
// settings modal ---
{
...Input_Template_System_Prompt,
label: 'core.ai.Prompt',
description: chatNodeSystemPromptTip,
placeholder: chatNodeSystemPromptTip
},
Input_Template_History,
{ ...Input_Template_UserChatInput, toolDescription: '用户问题' },
Input_Template_Dataset_Quote
],
outputs: [
{
id: NodeOutputKeyEnum.history,
key: NodeOutputKeyEnum.history,
label: 'core.module.output.label.New context',
description: 'core.module.output.description.New context',
valueType: WorkflowIOValueTypeEnum.chatHistory,
type: FlowNodeOutputTypeEnum.static
},
{
id: NodeOutputKeyEnum.answerText,
key: NodeOutputKeyEnum.answerText,
label: 'core.module.output.label.Ai response content',
description: 'core.module.output.description.Ai response content',
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
]
};

View File

@@ -0,0 +1,36 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
FlowNodeTemplateTypeEnum,
NodeOutputKeyEnum
} from '../../constants';
import { getHandleConfig } from '../utils';
export const AssignedAnswerModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.answerNode,
templateType: FlowNodeTemplateTypeEnum.textAnswer,
flowNodeType: FlowNodeTypeEnum.answerNode,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/reply.png',
name: '指定回复',
intro:
'该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。',
inputs: [
{
key: NodeInputKeyEnum.answerText,
renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.string,
label: 'core.module.input.label.Response content',
description: 'core.module.input.description.Response content',
placeholder: 'core.module.input.description.Response content'
}
],
outputs: []
};

View File

@@ -3,32 +3,33 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
FlowNodeTemplateTypeEnum
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
FlowNodeTemplateTypeEnum,
NodeOutputKeyEnum
} from '../../constants';
import {
Input_Template_SelectAIModel,
Input_Template_History,
Input_Template_Switch,
Input_Template_UserChatInput
} from '../input';
import { Output_Template_UserChatInput } from '../output';
import { Input_Template_System_Prompt } from '../input';
import { LLMModelTypeEnum } from '../../../ai/constants';
import { getHandleConfig } from '../utils';
export const ClassifyQuestionModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.classifyQuestion,
templateType: FlowNodeTemplateTypeEnum.functionCall,
flowType: FlowNodeTypeEnum.classifyQuestion,
avatar: '/imgs/module/cq.png',
flowNodeType: FlowNodeTypeEnum.classifyQuestion,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(true, false, true, true),
avatar: '/imgs/workflow/cq.png',
name: '问题分类',
intro: `根据用户的历史记录和当前问题判断该次提问的类型。可以添加多组问题类型,下面是一个模板例子:\n类型1: 打招呼\n类型2: 关于商品“使用”问题\n类型3: 关于商品“购买”问题\n类型4: 其他问题`,
showStatus: true,
inputs: [
Input_Template_Switch,
{
...Input_Template_SelectAIModel,
llmModelType: LLMModelTypeEnum.classify
@@ -42,9 +43,9 @@ export const ClassifyQuestionModule: FlowNodeTemplateType = {
Input_Template_History,
Input_Template_UserChatInput,
{
key: ModuleInputKeyEnum.agents,
type: FlowNodeInputTypeEnum.custom,
valueType: ModuleIOValueTypeEnum.any,
key: NodeInputKeyEnum.agents,
renderTypeList: [FlowNodeInputTypeEnum.custom],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
value: [
{
@@ -59,31 +60,16 @@ export const ClassifyQuestionModule: FlowNodeTemplateType = {
value: '其他问题',
key: 'agex'
}
],
showTargetInApp: false,
showTargetInPlugin: false
]
}
],
outputs: [
Output_Template_UserChatInput,
// custom output
{
key: 'wqre',
label: '',
type: FlowNodeOutputTypeEnum.hidden,
targets: []
},
{
key: 'sdfa',
label: '',
type: FlowNodeOutputTypeEnum.hidden,
targets: []
},
{
key: 'agex',
label: '',
type: FlowNodeOutputTypeEnum.hidden,
targets: []
id: NodeOutputKeyEnum.cqResult,
key: NodeOutputKeyEnum.cqResult,
label: '分类结果',
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
]
};

View File

@@ -0,0 +1,86 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_SelectAIModel, Input_Template_History } from '../input';
import { LLMModelTypeEnum } from '../../../ai/constants';
import { getHandleConfig } from '../utils';
export const ContextExtractModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.contentExtract,
templateType: FlowNodeTemplateTypeEnum.functionCall,
flowNodeType: FlowNodeTypeEnum.contentExtract,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/extract.png',
name: '文本内容提取',
intro: '可从文本中提取指定的数据例如sql语句、搜索关键词、代码等',
showStatus: true,
isTool: true,
inputs: [
{
...Input_Template_SelectAIModel,
llmModelType: LLMModelTypeEnum.extractFields
},
{
key: NodeInputKeyEnum.description,
renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.string,
label: '提取要求描述',
description:
'给AI一些对应的背景知识或要求描述引导AI更好的完成任务。\n该输入框可使用全局变量。',
placeholder:
'例如: \n1. 当前时间为: {{cTime}}。你是一个实验室预约助手,你的任务是帮助用户预约实验室,从文本中获取对应的预约信息。\n2. 你是谷歌搜索助手,需要从文本中提取出合适的搜索词。'
},
Input_Template_History,
{
key: NodeInputKeyEnum.contextExtractInput,
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.textarea],
label: '需要提取的文本',
required: true,
valueType: WorkflowIOValueTypeEnum.string,
toolDescription: '需要检索的内容'
},
{
key: NodeInputKeyEnum.extractKeys,
renderTypeList: [FlowNodeInputTypeEnum.custom],
label: '',
valueType: WorkflowIOValueTypeEnum.any,
description: "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段",
value: [] // {desc: string; key: string; required: boolean; enum: string[]}[]
}
],
outputs: [
// {
// id: NodeOutputKeyEnum.success,
// key: NodeOutputKeyEnum.success,
// label: '字段完全提取',
// valueType: WorkflowIOValueTypeEnum.boolean,
// type: FlowNodeOutputTypeEnum.source
// },
// {
// id: NodeOutputKeyEnum.failed,
// key: NodeOutputKeyEnum.failed,
// label: '提取字段缺失',
// description: '存在一个或多个字段未提取成功。尽管使用了默认值也算缺失。',
// valueType: WorkflowIOValueTypeEnum.boolean,
// type: FlowNodeOutputTypeEnum.source
// },
{
id: NodeOutputKeyEnum.contextExtractFields,
key: NodeOutputKeyEnum.contextExtractFields,
label: '完整提取结果',
description: '一个 JSON 字符串,例如:{"name:":"YY","Time":"2023/7/2 18:00"}',
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
]
};

View File

@@ -0,0 +1,59 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_Dataset_Quote } from '../input';
import { getNanoid } from '../../../../common/string/tools';
import { getHandleConfig } from '../utils';
import { FlowNodeInputItemType } from '../../type/io.d';
export const getOneQuoteInputTemplate = (key = getNanoid()): FlowNodeInputItemType => ({
...Input_Template_Dataset_Quote,
key,
renderTypeList: [FlowNodeInputTypeEnum.custom],
description: ''
});
export const DatasetConcatModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.datasetConcatNode,
flowNodeType: FlowNodeTypeEnum.datasetConcatNode,
templateType: FlowNodeTemplateTypeEnum.other,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/concat.svg',
name: '知识库搜索引用合并',
intro: '可以将多个知识库搜索结果进行合并输出。使用 RRF 的合并方式进行最终排序输出。',
showStatus: false,
inputs: [
{
key: NodeInputKeyEnum.datasetMaxTokens,
renderTypeList: [FlowNodeInputTypeEnum.custom],
label: '最大 Tokens',
value: 1500,
valueType: WorkflowIOValueTypeEnum.number
},
{
key: 'customComponent',
renderTypeList: [FlowNodeInputTypeEnum.custom],
label: ''
},
getOneQuoteInputTemplate()
],
outputs: [
{
id: NodeOutputKeyEnum.datasetQuoteQA,
key: NodeOutputKeyEnum.datasetQuoteQA,
label: 'core.module.Dataset quote.label',
type: FlowNodeOutputTypeEnum.static,
valueType: WorkflowIOValueTypeEnum.datasetQuote
}
]
};

View File

@@ -0,0 +1,105 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_UserChatInput } from '../input';
import { DatasetSearchModeEnum } from '../../../dataset/constants';
import { getHandleConfig } from '../utils';
export const Dataset_SEARCH_DESC =
'调用“语义检索”和“全文检索”能力,从“知识库”中查找可能与问题相关的参考内容';
export const DatasetSearchModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.datasetSearchNode,
templateType: FlowNodeTemplateTypeEnum.functionCall,
flowNodeType: FlowNodeTypeEnum.datasetSearchNode,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/db.png',
name: '知识库搜索',
intro: Dataset_SEARCH_DESC,
showStatus: true,
isTool: true,
inputs: [
{
key: NodeInputKeyEnum.datasetSelectList,
renderTypeList: [FlowNodeInputTypeEnum.selectDataset, FlowNodeInputTypeEnum.reference],
label: 'core.module.input.label.Select dataset',
value: [],
valueType: WorkflowIOValueTypeEnum.selectDataset,
list: [],
required: true
},
{
key: NodeInputKeyEnum.datasetSimilarity,
renderTypeList: [FlowNodeInputTypeEnum.selectDatasetParamsModal],
label: '',
value: 0.4,
valueType: WorkflowIOValueTypeEnum.number
},
// setting from modal
{
key: NodeInputKeyEnum.datasetMaxTokens,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
value: 1500,
valueType: WorkflowIOValueTypeEnum.number
},
{
key: NodeInputKeyEnum.datasetSearchMode,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string,
value: DatasetSearchModeEnum.embedding
},
{
key: NodeInputKeyEnum.datasetSearchUsingReRank,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.boolean,
value: false
},
{
key: NodeInputKeyEnum.datasetSearchUsingExtensionQuery,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.boolean,
value: true
},
{
key: NodeInputKeyEnum.datasetSearchExtensionModel,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
},
{
key: NodeInputKeyEnum.datasetSearchExtensionBg,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string,
value: ''
},
{
...Input_Template_UserChatInput,
toolDescription: '需要检索的内容'
}
],
outputs: [
{
id: NodeOutputKeyEnum.datasetQuoteQA,
key: NodeOutputKeyEnum.datasetQuoteQA,
label: 'core.module.Dataset quote.label',
description: '特殊数组格式,搜索结果为空时,返回空数组。',
type: FlowNodeOutputTypeEnum.static,
valueType: WorkflowIOValueTypeEnum.datasetQuote
}
]
};

View File

@@ -0,0 +1,17 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { getHandleConfig } from '../utils';
export const EmptyNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.emptyNode,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.emptyNode,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, false),
avatar: '',
name: '',
intro: '',
inputs: [],
outputs: []
};

View File

@@ -0,0 +1,31 @@
import { FlowNodeTemplateTypeEnum, WorkflowIOValueTypeEnum } from '../../constants';
import { getHandleConfig } from '../utils';
import { FlowNodeTypeEnum } from '../../node/constant';
import { VariableItemType } from '../../../app/type';
import { FlowNodeTemplateType } from '../../type';
export const getGlobalVariableNode = ({
id,
variables
}: {
id: string;
variables: VariableItemType[];
}): FlowNodeTemplateType => {
return {
id,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.systemConfig,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/variable.png',
name: '全局变量',
intro: '',
inputs: [],
outputs: variables.map((item) => ({
id: item.key,
key: item.key,
valueType: WorkflowIOValueTypeEnum.string,
label: item.label
}))
};
};

View File

@@ -0,0 +1,92 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_DynamicInput } from '../input';
import { Output_Template_AddOutput } from '../output';
import { getHandleConfig } from '../utils';
export const HttpModule468: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.httpRequest468,
templateType: FlowNodeTemplateTypeEnum.externalCall,
flowNodeType: FlowNodeTypeEnum.httpRequest468,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/http.png',
name: 'HTTP 请求',
intro: '可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
showStatus: true,
isTool: true,
inputs: [
{
...Input_Template_DynamicInput,
description: 'core.module.input.description.HTTP Dynamic Input',
editField: {
key: true,
valueType: true
}
},
{
key: NodeInputKeyEnum.httpMethod,
renderTypeList: [FlowNodeInputTypeEnum.custom],
valueType: WorkflowIOValueTypeEnum.string,
label: '',
value: 'POST',
required: true
},
{
key: NodeInputKeyEnum.httpReqUrl,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.string,
label: '',
description: 'core.module.input.description.Http Request Url',
placeholder: 'https://api.ai.com/getInventory',
required: false
},
{
key: NodeInputKeyEnum.httpHeaders,
renderTypeList: [FlowNodeInputTypeEnum.custom],
valueType: WorkflowIOValueTypeEnum.any,
value: [],
label: '',
description: 'core.module.input.description.Http Request Header',
placeholder: 'core.module.input.description.Http Request Header',
required: false
},
{
key: NodeInputKeyEnum.httpParams,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
value: [],
label: '',
required: false
},
{
key: NodeInputKeyEnum.httpJsonBody,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
value: '',
label: '',
required: false
}
],
outputs: [
Output_Template_AddOutput,
{
id: NodeOutputKeyEnum.httpRawResponse,
key: NodeOutputKeyEnum.httpRawResponse,
label: '原始响应',
description: 'HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。',
valueType: WorkflowIOValueTypeEnum.any,
type: FlowNodeOutputTypeEnum.static
}
]
};

View File

@@ -0,0 +1,84 @@
export enum VariableConditionEnum {
equalTo = 'equalTo',
notEqual = 'notEqual',
isEmpty = 'isEmpty',
isNotEmpty = 'isNotEmpty',
include = 'include',
notInclude = 'notInclude',
startWith = 'startWith',
endWith = 'endWith',
greaterThan = 'greaterThan',
greaterThanOrEqualTo = 'greaterThanOrEqualTo',
lessThan = 'lessThan',
lessThanOrEqualTo = 'lessThanOrEqualTo',
lengthEqualTo = 'lengthEqualTo',
lengthNotEqualTo = 'lengthNotEqualTo',
lengthGreaterThan = 'lengthGreaterThan',
lengthGreaterThanOrEqualTo = 'lengthGreaterThanOrEqualTo',
lengthLessThan = 'lengthLessThan',
lengthLessThanOrEqualTo = 'lengthLessThanOrEqualTo'
}
export const stringConditionList = [
{ label: '为空', value: VariableConditionEnum.isEmpty },
{ label: '不为空', value: VariableConditionEnum.isNotEmpty },
{ label: '等于', value: VariableConditionEnum.equalTo },
{ label: '不等于', value: VariableConditionEnum.notEqual },
{ label: '包含', value: VariableConditionEnum.include },
{ label: '不包含', value: VariableConditionEnum.notInclude },
{ label: '开始为', value: VariableConditionEnum.startWith },
{ label: '结束为', value: VariableConditionEnum.endWith }
];
export const numberConditionList = [
{ label: '为空', value: VariableConditionEnum.isEmpty },
{ label: '不为空', value: VariableConditionEnum.isNotEmpty },
{ label: '等于', value: VariableConditionEnum.equalTo },
{ label: '不等于', value: VariableConditionEnum.notEqual },
{ label: '大于', value: VariableConditionEnum.greaterThan },
{ label: '大于等于', value: VariableConditionEnum.greaterThanOrEqualTo },
{ label: '小于', value: VariableConditionEnum.lessThan },
{ label: '小于等于', value: VariableConditionEnum.lessThanOrEqualTo }
];
export const booleanConditionList = [
{ label: '为空', value: VariableConditionEnum.isEmpty },
{ label: '不为空', value: VariableConditionEnum.isNotEmpty },
{ label: '等于', value: VariableConditionEnum.equalTo }
];
export const arrayConditionList = [
{ label: '为空', value: VariableConditionEnum.isEmpty },
{ label: '不为空', value: VariableConditionEnum.isNotEmpty },
{ label: '包含', value: VariableConditionEnum.include },
{ label: '不包含', value: VariableConditionEnum.notInclude },
{ label: '长度等于', value: VariableConditionEnum.lengthEqualTo },
{ label: '长度不等于', value: VariableConditionEnum.lengthNotEqualTo },
{ label: '长度大于', value: VariableConditionEnum.lengthGreaterThan },
{ label: '长度大于等于', value: VariableConditionEnum.lengthGreaterThanOrEqualTo },
{ label: '长度小于', value: VariableConditionEnum.lengthLessThan },
{ label: '长度小于等于', value: VariableConditionEnum.lengthLessThanOrEqualTo }
];
export const objectConditionList = [
{ label: '为空', value: VariableConditionEnum.isEmpty },
{ label: '不为空', value: VariableConditionEnum.isNotEmpty }
];
export const allConditionList = [
{ label: '为空', value: VariableConditionEnum.isEmpty },
{ label: '不为空', value: VariableConditionEnum.isNotEmpty },
{ label: '等于', value: VariableConditionEnum.equalTo },
{ label: '不等于', value: VariableConditionEnum.notEqual },
{ label: '包含', value: VariableConditionEnum.include },
{ label: '不包含', value: VariableConditionEnum.notInclude },
{ label: '开始为', value: VariableConditionEnum.startWith },
{ label: '结束为', value: VariableConditionEnum.endWith },
{ label: '大于', value: VariableConditionEnum.greaterThan },
{ label: '大于等于', value: VariableConditionEnum.greaterThanOrEqualTo },
{ label: '小于', value: VariableConditionEnum.lessThan },
{ label: '小于等于', value: VariableConditionEnum.lessThanOrEqualTo },
{ label: '长度等于', value: VariableConditionEnum.lengthEqualTo },
{ label: '长度不等于', value: VariableConditionEnum.lengthNotEqualTo },
{ label: '长度大于', value: VariableConditionEnum.lengthGreaterThan },
{ label: '长度大于等于', value: VariableConditionEnum.lengthGreaterThanOrEqualTo },
{ label: '长度小于', value: VariableConditionEnum.lengthLessThan },
{ label: '长度小于等于', value: VariableConditionEnum.lengthLessThanOrEqualTo }
];

View File

@@ -0,0 +1,64 @@
import {
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
WorkflowIOValueTypeEnum
} from '../../../constants';
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type';
import { getHandleConfig } from '../../utils';
export const ifElseNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.ifElseNode,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.ifElseNode,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(true, false, true, true),
avatar: '/imgs/workflow/ifElse.svg',
name: '判断器',
intro: '根据一定的条件,执行不同的分支。',
showStatus: true,
inputs: [
{
key: NodeInputKeyEnum.condition,
valueType: WorkflowIOValueTypeEnum.string,
label: '',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
required: false,
value: 'AND' // AND, OR
},
{
key: NodeInputKeyEnum.ifElseList,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
value: [
{
variable: undefined,
condition: undefined,
value: undefined
}
]
}
],
outputs: [
{
id: NodeOutputKeyEnum.if,
key: NodeOutputKeyEnum.if,
label: 'IF',
valueType: WorkflowIOValueTypeEnum.any,
type: FlowNodeOutputTypeEnum.source
},
{
id: NodeOutputKeyEnum.else,
key: NodeOutputKeyEnum.else,
label: 'ELSE',
valueType: WorkflowIOValueTypeEnum.any,
type: FlowNodeOutputTypeEnum.source
}
]
};

View File

@@ -0,0 +1,9 @@
import { ReferenceValueProps } from 'core/workflow/type/io';
import { VariableConditionEnum } from './constant';
export type IfElseConditionType = 'AND' | 'OR';
export type IfElseListItemType = {
variable?: ReferenceValueProps;
condition?: VariableConditionEnum;
value?: string;
};

View File

@@ -0,0 +1,60 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_DynamicInput } from '../input';
import { Output_Template_AddOutput } from '../output';
import { getHandleConfig } from '../utils';
export const lafModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.lafModule,
templateType: FlowNodeTemplateTypeEnum.externalCall,
flowNodeType: FlowNodeTypeEnum.lafModule,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/laf.png',
name: 'Laf 函数调用(测试)',
intro: '可以调用Laf账号下的云函数。',
showStatus: true,
isTool: true,
inputs: [
{
...Input_Template_DynamicInput,
description: '接收前方节点的输出值作为变量,这些变量可以被 Laf 请求参数使用。',
editField: {
key: true,
valueType: true
}
},
{
key: NodeInputKeyEnum.httpReqUrl,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.string,
label: '',
description: 'core.module.input.description.Http Request Url',
placeholder: 'https://api.ai.com/getInventory',
required: false
}
],
outputs: [
{
id: NodeOutputKeyEnum.httpRawResponse,
key: NodeOutputKeyEnum.httpRawResponse,
label: '原始响应',
description: 'HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。',
valueType: WorkflowIOValueTypeEnum.any,
type: FlowNodeOutputTypeEnum.static
},
{
...Output_Template_AddOutput
}
]
};

View File

@@ -0,0 +1,20 @@
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import { getHandleConfig } from '../utils';
export const PluginInputModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.pluginInput,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.pluginInput,
sourceHandle: getHandleConfig(false, true, false, false),
targetHandle: getHandleConfig(false, false, false, false),
unique: true,
forbidDelete: true,
avatar: '/imgs/workflow/input.png',
name: '定义插件输入',
intro: '自定义配置外部输入,使用插件时,仅暴露自定义配置的输入',
showStatus: false,
inputs: [],
outputs: []
};

View File

@@ -1,12 +1,17 @@
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type';
import { getHandleConfig } from '../utils';
export const PluginOutputModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.pluginOutput,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowType: FlowNodeTypeEnum.pluginOutput,
avatar: '/imgs/module/output.png',
flowNodeType: FlowNodeTypeEnum.pluginOutput,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, true),
unique: true,
forbidDelete: true,
avatar: '/imgs/workflow/output.png',
name: '定义插件输出',
intro: '自定义配置外部输出,使用插件时,仅暴露自定义配置的输出',
showStatus: false,

View File

@@ -3,60 +3,57 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import { FlowNodeTemplateType } from '../../type/index.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import {
Input_Template_History,
Input_Template_Switch,
Input_Template_UserChatInput,
Input_Template_SelectAIModel
} from '../input';
import { Output_Template_UserChatInput } from '../output';
import { LLMModelTypeEnum } from '../../../ai/constants';
import { getHandleConfig } from '../utils';
export const AiQueryExtension: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.chatNode,
templateType: FlowNodeTemplateTypeEnum.other,
flowType: FlowNodeTypeEnum.queryExtension,
avatar: '/imgs/module/cfr.svg',
flowNodeType: FlowNodeTypeEnum.queryExtension,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/cfr.svg',
name: '问题优化',
intro:
'使用问题优化功能,可以提高知识库连续对话时搜索的精度。使用该功能后,会先利用 AI 根据上下文构建一个或多个新的检索词,这些检索词更利于进行知识库搜索。该模块已内置在知识库搜索模块中,如果您仅进行一次知识库搜索,可直接使用知识库内置的补全功能。',
showStatus: true,
inputs: [
Input_Template_Switch,
{
...Input_Template_SelectAIModel,
llmModelType: LLMModelTypeEnum.queryExtension
},
{
key: ModuleInputKeyEnum.aiSystemPrompt,
type: FlowNodeInputTypeEnum.textarea,
key: NodeInputKeyEnum.aiSystemPrompt,
renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference],
label: 'core.app.edit.Query extension background prompt',
max: 300,
valueType: ModuleIOValueTypeEnum.string,
valueType: WorkflowIOValueTypeEnum.string,
description: 'core.app.edit.Query extension background tip',
placeholder: 'core.module.QueryExtension.placeholder',
showTargetInApp: true,
showTargetInPlugin: true
placeholder: 'core.module.QueryExtension.placeholder'
},
Input_Template_History,
Input_Template_UserChatInput
],
outputs: [
Output_Template_UserChatInput,
{
key: ModuleOutputKeyEnum.text,
id: NodeOutputKeyEnum.text,
key: NodeOutputKeyEnum.text,
label: 'core.module.output.label.query extension result',
description: 'core.module.output.description.query extension result',
valueType: ModuleIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.source,
targets: []
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
]
};

View File

@@ -0,0 +1,56 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_History, Input_Template_UserChatInput } from '../input';
import { getHandleConfig } from '../utils';
export const RunAppModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.runApp,
templateType: FlowNodeTemplateTypeEnum.externalCall,
flowNodeType: FlowNodeTypeEnum.runApp,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/app.png',
name: '应用调用',
intro: '可以选择一个其他应用进行调用',
showStatus: true,
inputs: [
{
key: NodeInputKeyEnum.runAppSelectApp,
renderTypeList: [FlowNodeInputTypeEnum.selectApp, FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.selectApp,
label: '选择一个应用',
description: '选择一个其他应用进行调用',
required: true
},
Input_Template_History,
Input_Template_UserChatInput
],
outputs: [
{
id: NodeOutputKeyEnum.history,
key: NodeOutputKeyEnum.history,
label: '新的上下文',
description: '将该应用回复内容拼接到历史记录中,作为新的上下文返回',
valueType: WorkflowIOValueTypeEnum.chatHistory,
type: FlowNodeOutputTypeEnum.static
},
{
id: NodeOutputKeyEnum.answerText,
key: NodeOutputKeyEnum.answerText,
label: '回复的文本',
description: '将在应用完全结束后触发',
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
]
};

View File

@@ -1,11 +1,14 @@
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type';
import { getHandleConfig } from '../utils';
export const RunPluginModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.pluginModule,
templateType: FlowNodeTemplateTypeEnum.externalCall,
flowType: FlowNodeTypeEnum.pluginModule,
flowNodeType: FlowNodeTypeEnum.pluginModule,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
intro: '',
name: '',
showStatus: false,

View File

@@ -1,16 +1,18 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { Input_Template_Switch } from '../input';
import { getHandleConfig } from '../utils';
export const StopToolNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.stopTool,
templateType: FlowNodeTemplateTypeEnum.functionCall,
flowType: FlowNodeTypeEnum.stopTool,
avatar: '/imgs/module/toolStop.svg',
flowNodeType: FlowNodeTypeEnum.stopTool,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/toolStop.svg',
name: '工具调用终止',
intro:
'该模块需配置工具调用使用。当该模块被执行时本次工具调用将会强制结束并且不再调用AI针对工具调用结果回答问题。',
inputs: [Input_Template_Switch],
inputs: [],
outputs: []
};

View File

@@ -0,0 +1,61 @@
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { getHandleConfig } from '../utils';
export const SystemConfigNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.systemConfig,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.systemConfig,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, false),
avatar: '/imgs/workflow/userGuide.png',
name: '系统配置',
intro: '可以配置应用的系统参数。',
unique: true,
forbidDelete: true,
inputs: [
{
key: NodeInputKeyEnum.welcomeText,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.string,
label: 'core.app.Welcome Text'
},
{
key: NodeInputKeyEnum.variables,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: 'core.module.Variable',
value: []
},
{
key: NodeInputKeyEnum.questionGuide,
valueType: WorkflowIOValueTypeEnum.boolean,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: ''
},
{
key: NodeInputKeyEnum.tts,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: ''
},
{
key: NodeInputKeyEnum.whisper,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: ''
},
{
key: NodeInputKeyEnum.scheduleTrigger,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: ''
}
],
outputs: []
};

View File

@@ -3,61 +3,57 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type/index.d';
import {
ModuleIOValueTypeEnum,
ModuleOutputKeyEnum,
WorkflowIOValueTypeEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum,
ModuleInputKeyEnum
NodeInputKeyEnum
} from '../../constants';
import {
Input_Template_SettingAiModel,
Input_Template_History,
Input_Template_Switch,
Input_Template_System_Prompt,
Input_Template_UserChatInput
} from '../input';
import { chatNodeSystemPromptTip } from '../tip';
import { Output_Template_Finish, Output_Template_UserChatInput } from '../output';
import { LLMModelTypeEnum } from '../../../ai/constants';
import { getHandleConfig } from '../utils';
export const ToolModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.tools,
flowType: FlowNodeTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.tools,
templateType: FlowNodeTemplateTypeEnum.functionCall,
avatar: '/imgs/module/tool.svg',
sourceHandle: getHandleConfig(true, true, false, true),
targetHandle: getHandleConfig(true, true, false, true),
avatar: '/imgs/workflow/tool.svg',
name: '工具调用(实验)',
intro: '通过AI模型自动选择一个或多个功能块进行调用也可以对插件进行调用。',
showStatus: true,
inputs: [
Input_Template_Switch,
{
...Input_Template_SettingAiModel,
llmModelType: LLMModelTypeEnum.all
},
{
key: ModuleInputKeyEnum.aiChatTemperature,
type: FlowNodeInputTypeEnum.hidden, // Set in the pop-up window
key: NodeInputKeyEnum.aiChatTemperature,
renderTypeList: [FlowNodeInputTypeEnum.hidden], // Set in the pop-up window
label: '',
value: 0,
valueType: ModuleIOValueTypeEnum.number,
valueType: WorkflowIOValueTypeEnum.number,
min: 0,
max: 10,
step: 1,
showTargetInApp: false,
showTargetInPlugin: false
step: 1
},
{
key: ModuleInputKeyEnum.aiChatMaxToken,
type: FlowNodeInputTypeEnum.hidden, // Set in the pop-up window
key: NodeInputKeyEnum.aiChatMaxToken,
renderTypeList: [FlowNodeInputTypeEnum.hidden], // Set in the pop-up window
label: '',
value: 2000,
valueType: ModuleIOValueTypeEnum.number,
valueType: WorkflowIOValueTypeEnum.number,
min: 100,
max: 4000,
step: 50,
showTargetInApp: false,
showTargetInPlugin: false
step: 50
},
{
...Input_Template_System_Prompt,
@@ -68,14 +64,5 @@ export const ToolModule: FlowNodeTemplateType = {
Input_Template_History,
Input_Template_UserChatInput
],
outputs: [
Output_Template_UserChatInput,
{
key: ModuleOutputKeyEnum.selectedTools,
valueType: ModuleIOValueTypeEnum.tools,
type: FlowNodeOutputTypeEnum.hidden,
targets: []
},
Output_Template_Finish
]
outputs: []
};

View File

@@ -0,0 +1,32 @@
import { FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import {
WorkflowIOValueTypeEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { getHandleConfig } from '../utils';
import { Input_Template_UserChatInput } from '../input';
export const WorkflowStart: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.workflowStart,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.workflowStart,
sourceHandle: getHandleConfig(false, true, false, false),
targetHandle: getHandleConfig(false, false, false, false),
avatar: '/imgs/workflow/userChatInput.svg',
name: '流程开始',
intro: '',
forbidDelete: true,
unique: true,
inputs: [{ ...Input_Template_UserChatInput, toolDescription: '用户问题' }],
outputs: [
{
id: NodeOutputKeyEnum.userChatInput,
key: NodeOutputKeyEnum.userChatInput,
label: 'core.module.input.label.user question',
type: FlowNodeOutputTypeEnum.static,
valueType: WorkflowIOValueTypeEnum.string
}
]
};

View File

@@ -0,0 +1,6 @@
export const getHandleConfig = (top: boolean, right: boolean, bottom: boolean, left: boolean) => ({
top,
right,
bottom,
left
});

View File

@@ -0,0 +1,12 @@
import { RuntimeEdgeStatusEnum } from '../constants';
export type StoreEdgeItemType = {
source: string;
sourceHandle: string;
target: string;
targetHandle: string;
};
export type RuntimeEdgeItemType = StoreEdgeItemType & {
status: `${RuntimeEdgeStatusEnum}`;
};

View File

@@ -0,0 +1,45 @@
export type FlowNodeChangeProps = { nodeId: string } & (
| {
type: 'attr'; // key: attr, value: new value
key: string;
value: any;
}
| {
type: 'updateInput'; // key: update input key, value: new input value
key: string;
value: any;
}
| {
type: 'replaceInput'; // key: old input key, value: new input value
key: string;
value: any;
}
| {
type: 'addInput'; // key: null, value: new input value
value: any;
index?: number;
}
| {
type: 'delInput'; // key: delete input key, value: null
key: string;
}
| {
type: 'updateOutput'; // key: update output key, value: new output value
key: string;
value: any;
}
| {
type: 'replaceOutput'; // key: old output key, value: new output value
key: string;
value: any;
}
| {
type: 'addOutput'; // key: null, value: new output value
value: any;
index?: number;
}
| {
type: 'delOutput'; // key: delete output key, value: null
key: string;
}
);

View File

@@ -0,0 +1,147 @@
import { FlowNodeTypeEnum } from '../node/constant';
import {
WorkflowIOValueTypeEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum,
VariableInputEnum
} from '../constants';
import { DispatchNodeResponseKeyEnum } from '../runtime/constants';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from './io.d';
import { UserModelSchema } from '../../../support/user/type';
import {
ChatHistoryItemResType,
ChatItemType,
ChatItemValueItemType,
ToolRunResponseItemType,
UserChatItemValueItemType
} from '../../chat/type';
import { ChatNodeUsageType } from '../../../support/wallet/bill/type';
import { RuntimeNodeItemType } from '../runtime/type';
import { PluginTypeEnum } from '../../plugin/constants';
import { RuntimeEdgeItemType, StoreEdgeItemType } from './edge';
import { NextApiResponse } from 'next';
export type FlowNodeCommonType = {
flowNodeType: `${FlowNodeTypeEnum}`; // render node card
avatar?: string;
name: string;
intro?: string; // template list intro
showStatus?: boolean; // chatting response step status
// data
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
// plugin data
pluginId?: string;
pluginType?: `${PluginTypeEnum}`;
parentId?: string;
};
export type FlowNodeTemplateType = FlowNodeCommonType & {
id: string; // module id, unique
templateType: `${FlowNodeTemplateTypeEnum}`;
// show handle
sourceHandle?: {
left: boolean;
right: boolean;
top: boolean;
bottom: boolean;
};
targetHandle?: {
left: boolean;
right: boolean;
top: boolean;
bottom: boolean;
};
// info
isTool?: boolean; // can be connected by tool
// action
forbidDelete?: boolean; // forbid delete
unique?: boolean;
};
export type FlowNodeItemType = FlowNodeTemplateType & {
nodeId: string;
isError?: boolean;
debugResult?: {
status: 'running' | 'success' | 'skipped' | 'failed';
message?: string;
showResult?: boolean; // show and hide result modal
response?: ChatHistoryItemResType;
isExpired?: boolean;
};
};
export type nodeTemplateListType = {
type: `${FlowNodeTemplateTypeEnum}`;
label: string;
list: FlowNodeTemplateType[];
}[];
// store node type
export type StoreNodeItemType = FlowNodeCommonType & {
nodeId: string;
position?: {
x: number;
y: number;
};
};
/* connection type */
export type NodeTargetNodeItemType = {
nodeId: string;
sourceHandle: string;
targetHandle: string;
};
export type NodeSourceNodeItemType = {
nodeId: string;
};
/* --------------- function type -------------------- */
export type SelectAppItemType = {
id: string;
name: string;
logo: string;
};
/* agent */
export type ClassifyQuestionAgentItemType = {
value: string;
key: string;
};
export type ContextExtractAgentItemType = {
desc: string;
key: string;
required: boolean;
defaultValue?: string;
enum?: string;
};
/* -------------- running module -------------- */
export type ChatDispatchProps = {
res?: NextApiResponse;
mode: 'test' | 'chat' | 'debug';
teamId: string;
tmbId: string;
user: UserModelSchema;
appId?: string;
chatId?: string;
responseChatItemId?: string;
histories: ChatItemType[];
variables: Record<string, any>;
inputFiles?: UserChatItemValueItemType['file'][];
stream: boolean;
detail: boolean; // response detail
maxRunTimes: number;
};
export type ModuleDispatchProps<T> = ChatDispatchProps & {
node: RuntimeNodeItemType;
runtimeNodes: RuntimeNodeItemType[];
runtimeEdges: RuntimeEdgeItemType[];
params: T;
};

View File

@@ -0,0 +1,61 @@
import { LLMModelTypeEnum } from '../../ai/constants';
import { WorkflowIOValueTypeEnum, NodeInputKeyEnum, NodeOutputKeyEnum } from '../constants';
import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum } from '../node/constant';
import { EditInputFieldMapType, EditNodeFieldType, EditOutputFieldMapType } from '../node/type';
export type FlowNodeInputItemType = {
selectedTypeIndex?: number;
renderTypeList: FlowNodeInputTypeEnum[]; // Node Type. Decide on a render style
key: `${NodeInputKeyEnum}` | string;
valueType?: WorkflowIOValueTypeEnum; // data type
value?: any;
label: string;
debugLabel?: string;
description?: string; // field desc
required?: boolean;
toolDescription?: string; // If this field is not empty, it is entered as a tool
maxLength?: number; // input,textarea
// edit
canEdit?: boolean;
// render components params
referencePlaceholder?: string;
placeholder?: string; // input,textarea
list?: { label: string; value: any }[]; // select
markList?: { label: string; value: any }[]; // slider
step?: number; // slider
max?: number; // slider, number input
min?: number; // slider, number input
defaultValue?: string;
// dynamic input
editField?: EditNodeFieldType['editField'];
dynamicParamDefaultValue?: EditNodeFieldType['dynamicParamDefaultValue'];
llmModelType?: `${LLMModelTypeEnum}`;
};
export type FlowNodeOutputItemType = {
id: string; // output unique id(Does not follow the key change)
type: `${FlowNodeOutputTypeEnum}`;
key: `${NodeOutputKeyEnum}` | string;
valueType?: WorkflowIOValueTypeEnum;
value?: any;
label?: string;
description?: string;
defaultValue?: any;
required?: boolean;
// component params
canEdit?: boolean;
editField?: EditOutputFieldMapType; // 添加
};
export type ReferenceValueProps = [string, string | undefined];

View File

@@ -0,0 +1,134 @@
import { FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from './node/constant';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
VariableInputEnum,
variableMap
} from './constants';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from './type/io.d';
import { StoreNodeItemType } from './type';
import type {
VariableItemType,
AppTTSConfigType,
AppWhisperConfigType,
AppScheduledTriggerConfigType
} from '../app/type';
import { EditorVariablePickerType } from '../../../web/components/common/Textarea/PromptEditor/type';
import { defaultWhisperConfig } from '../app/constants';
export const getHandleId = (nodeId: string, type: 'source' | 'target', key: string) => {
return `${nodeId}-${type}-${key}`;
};
export const checkInputIsReference = (input: FlowNodeInputItemType) => {
const value = input.value;
if (
Array.isArray(value) &&
value.length === 2 &&
typeof value[0] === 'string' &&
typeof value[1] === 'string'
) {
return true;
}
return false;
};
/* node */
export const getGuideModule = (modules: StoreNodeItemType[]) =>
modules.find((item) => item.flowNodeType === FlowNodeTypeEnum.systemConfig);
export const splitGuideModule = (guideModules?: StoreNodeItemType) => {
const welcomeText: string =
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.welcomeText)?.value || '';
const variableModules: VariableItemType[] =
guideModules?.inputs.find((item) => item.key === NodeInputKeyEnum.variables)?.value || [];
const questionGuide: boolean =
!!guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.questionGuide)?.value ||
false;
const ttsConfig: AppTTSConfigType = guideModules?.inputs?.find(
(item) => item.key === NodeInputKeyEnum.tts
)?.value || { type: 'web' };
const whisperConfig: AppWhisperConfigType =
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.whisper)?.value ||
defaultWhisperConfig;
const scheduledTriggerConfig: AppScheduledTriggerConfigType | null =
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.scheduleTrigger)?.value ??
null;
return {
welcomeText,
variableModules,
questionGuide,
ttsConfig,
whisperConfig,
scheduledTriggerConfig
};
};
export const getOrInitModuleInputValue = (input: FlowNodeInputItemType) => {
if (input.value !== undefined || !input.valueType) return input.value;
const map: Record<string, any> = {
[WorkflowIOValueTypeEnum.boolean]: false,
[WorkflowIOValueTypeEnum.number]: 0,
[WorkflowIOValueTypeEnum.string]: ''
};
return map[input.valueType];
};
export const getModuleInputUiField = (input: FlowNodeInputItemType) => {
// if (input.renderTypeList === FlowNodeInputTypeEnum.input || input.type === FlowNodeInputTypeEnum.textarea) {
// return {
// placeholder: input.placeholder || input.description
// };
// }
return {};
};
export const pluginData2FlowNodeIO = (
nodes: StoreNodeItemType[]
): {
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
} => {
const pluginInput = nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput);
const pluginOutput = nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginOutput);
return {
inputs: pluginInput
? pluginInput.inputs.map((item) => ({
...item,
...getModuleInputUiField(item),
value: getOrInitModuleInputValue(item),
canEdit: false
}))
: [],
outputs: pluginOutput
? [
...pluginOutput.inputs.map((item) => ({
id: item.key,
type: FlowNodeOutputTypeEnum.static,
key: item.key,
valueType: item.valueType,
label: item.label || item.key,
description: item.description
}))
]
: []
};
};
export const formatEditorVariablePickerIcon = (
variables: { key: string; label: string; type?: `${VariableInputEnum}` }[]
): EditorVariablePickerType[] => {
return variables.map((item) => ({
...item,
icon: item.type ? variableMap[item.type]?.icon : variableMap['input'].icon
}));
};