4.7-alpha2 (#1027)

* feat: stop toolCall and rename some field. (#46)

* perf: node delete tip;pay tip

* fix: toolCall cannot save child answer

* feat: stop tool

* fix: team modal

* fix feckbackMoal  auth bug (#47)

* 简单的支持提示词运行tool。优化workflow模板 (#49)

* remove templates

* fix: request body undefined

* feat: prompt tool run

* feat: workflow tamplates modal

* perf: plugin start

* 4.7 (#50)

* fix docker-compose download url (#994)

original code is a bad url with '404 NOT FOUND' return.
fix docker-compose download url, add 'v' before docker-compose version

* Update ai_settings.md (#1000)

* Update configuration.md

* Update configuration.md

* Fix history in classifyQuestion and extract modules (#1012)

* Fix history in classifyQuestion and extract modules

* Add chatValue2RuntimePrompt import and update text formatting

* flow controller to packages

* fix: rerank select

* modal ui

* perf: modal code path

* point not sufficient

* feat: http url support variable

* fix http key

* perf: prompt

* perf: ai setting modal

* simple edit ui

---------

Co-authored-by: entorick <entorick11@qq.com>
Co-authored-by: liujianglc <liujianglc@163.com>
Co-authored-by: Fengrui Liu <liufengrui.work@bytedance.com>

* fix team share redirect to login (#51)

* feat: support openapi import plugins (#48)

* feat: support openapi import plugins

* feat: import from url

* fix: add body params parse

* fix build

* fix

* fix

* fix

* tool box ui (#52)

* fix: training queue

* feat: simple edit tool select

* perf: simple edit dataset prompt

* fix: chatbox tool ux

* feat: quote prompt module

* perf: plugin tools sign

* perf: model avatar

* tool selector ui

* feat: max histories

* perf: http plugin import (#53)

* perf: plugin http import

* chatBox ui

* perf: name

* fix: Node template card (#54)

* fix: ts

* setting modal

* package

* package

* feat: add plugins search (#57)

* feat: add plugins search

* perf: change http plugin header input

* Yjl (#56)

* perf: prompt tool call

* perf: chat box ux

* doc

* doc

* price tip

* perf: tool selector

* ui'

* fix: vector queue

* fix: empty tool and empty response

* fix: empty msg

* perf: pg index

* perf: ui tip

* doc

* tool tip

---------

Co-authored-by: yst <77910600+yu-and-liu@users.noreply.github.com>
Co-authored-by: entorick <entorick11@qq.com>
Co-authored-by: liujianglc <liujianglc@163.com>
Co-authored-by: Fengrui Liu <liufengrui.work@bytedance.com>
Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
Archer
2024-03-21 13:32:31 +08:00
committed by GitHub
parent 6d4b331db9
commit 9d27de154b
322 changed files with 9282 additions and 6498 deletions

View File

@@ -15,7 +15,7 @@ export enum TeamErrEnum {
const teamErr = [
{ statusText: TeamErrEnum.teamOverSize, message: 'error.team.overSize' },
{ statusText: TeamErrEnum.unAuthTeam, message: '无权操作该团队' },
{ statusText: TeamErrEnum.aiPointsNotEnough, message: 'AI积分已用完~' },
{ statusText: TeamErrEnum.aiPointsNotEnough, message: '' },
{ statusText: TeamErrEnum.datasetSizeNotEnough, message: '知识库容量不足,请先扩容~' },
{ statusText: TeamErrEnum.datasetAmountNotEnough, message: '知识库数量已达上限~' },
{ statusText: TeamErrEnum.appAmountNotEnough, message: '应用数量已达上限~' },

View File

@@ -1,7 +1,7 @@
import { replaceSensitiveText } from '../string/tools';
export const getErrText = (err: any, def = '') => {
const msg: string = typeof err === 'string' ? err : err?.message || def || '';
const msg: string = typeof err === 'string' ? err : err?.message ?? def;
msg && console.log('error =>', msg);
return replaceSensitiveText(msg);
};

View File

@@ -1,3 +1,4 @@
/* mongo fs bucket */
export enum BucketNameEnum {
dataset = 'dataset'
}
@@ -7,4 +8,4 @@ export const bucketNameMap = {
}
};
export const FileBaseUrl = '/api/common/file/read';
export const ReadFileBaseUrl = '/api/common/file/read';

View File

@@ -50,3 +50,7 @@ export const mongoImageTypeMap = {
export const uniqueImageTypeList = Object.entries(mongoImageTypeMap)
.filter(([key, value]) => value.unique)
.map(([key]) => key as `${MongoImageTypeEnum}`);
export const FolderIcon = 'file/fill/folder';
export const FolderImgUrl = '/imgs/files/folder.svg';
export const HttpImgUrl = '/imgs/module/http.png';

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +1,3 @@
export const HUMAN_ICON = `/icon/human.svg`;
export const LOGO_ICON = `/icon/logo.svg`;
export const HUGGING_FACE_ICON = `/imgs/model/huggingface.svg`;

View File

@@ -1,6 +1,7 @@
export type LLMModelItemType = {
model: string;
name: string;
avatar?: string;
maxContext: number;
maxResponse: number;
quoteMaxToken: number;
@@ -31,6 +32,7 @@ export type LLMModelItemType = {
export type VectorModelItemType = {
model: string;
name: string;
avatar?: string;
defaultToken: number;
charsPointsPrice: number;
maxToken: number;

View File

@@ -0,0 +1,116 @@
import { PromptTemplateItem } from '../type.d';
export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
{
title: '标准模板',
desc: '标准提示词,用于结构不固定的知识库。',
value: `{{q}}
{{a}}`
},
{
title: '问答模板',
desc: '适合 QA 问答结构的知识库可以让AI较为严格的按预设内容回答',
value: `<Question>
{{q}}
</Question>
<Answer>
{{a}}
</Answer>`
},
{
title: '标准严格模板',
desc: '在标准模板基础上,对模型的回答做更严格的要求。',
value: `{{q}}
{{a}}`
},
{
title: '严格问答模板',
desc: '在问答模板基础上,对模型的回答做更严格的要求。',
value: `<Question>
{{q}}
</Question>
<Answer>
{{a}}
</Answer>`
}
];
export const Prompt_QuotePromptList: PromptTemplateItem[] = [
{
title: '标准模板',
desc: '',
value: `使用 <Data></Data> 标记中的内容作为你的知识:
<Data>
{{quote}}
</Data>
回答要求:
- 如果你不清楚答案,你需要澄清。
- 避免提及你是从 <Data></Data> 获取的知识。
- 保持答案与 <Data></Data> 中描述的一致。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。
问题:"""{{question}}"""`
},
{
title: '问答模板',
desc: '',
value: `使用 <QA></QA> 标记中的问答对进行回答。
<QA>
{{quote}}
</QA>
回答要求:
- 选择其中一个或多个问答对进行回答。
- 回答的内容应尽可能与 <答案></答案> 中的内容一致。
- 如果没有相关的问答对,你需要澄清。
- 避免提及你是从 QA 获取的知识,只需要回复答案。
问题:"""{{question}}"""`
},
{
title: '标准严格模板',
desc: '',
value: `忘记你已有的知识,仅使用 <Data></Data> 标记中的内容作为你的知识:
<Data>
{{quote}}
</Data>
思考流程:
1. 判断问题是否与 <Data></Data> 标记中的内容有关。
2. 如果有关,你按下面的要求回答。
3. 如果无关,你直接拒绝回答本次问题。
回答要求:
- 避免提及你是从 <Data></Data> 获取的知识。
- 保持答案与 <Data></Data> 中描述的一致。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。
问题:"""{{question}}"""`
},
{
title: '严格问答模板',
desc: '',
value: `忘记你已有的知识,仅使用 <QA></QA> 标记中的问答对进行回答。
<QA>
{{quote}}
</QA>}
思考流程:
1. 判断问题是否与 <QA></QA> 标记中的内容有关。
2. 如果无关,你直接拒绝回答本次问题。
3. 判断是否有相近或相同的问题。
4. 如果有相同的问题,直接输出对应答案。
5. 如果只有相近的问题,请把相近的问题和答案一起输出。
最后,避免提及你是从 QA 获取的知识,只需要回复答案。
问题:"""{{question}}"""`
}
];

View File

@@ -0,0 +1,60 @@
export const Prompt_AgentQA = {
description: `<Context></Context> 标记中是一段文本,学习和分析它,并整理学习成果:
- 提出问题并给出每个问题的答案。
- 答案需详细完整,尽可能保留原文描述。
- 答案可以包含普通文字、链接、代码、表格、公示、媒体链接等 Markdown 元素。
- 最多提出 30 个问题。
`,
fixedText: `请按以下格式整理学习成果:
<Context>
文本
</Context>
Q1: 问题。
A1: 答案。
Q2:
A2:
------
我们开始吧!
<Context>
{{text}}
<Context/>
`
};
export const Prompt_ExtractJson = `你可以从 <对话记录></对话记录> 中提取指定 JSON 信息,你仅需返回 JSON 字符串,无需回答问题。
<提取要求>
{{description}}
</提取要求>
<字段说明>
1. 下面的 JSON 字符串均按照 JSON Schema 的规则描述。
2. key 代表字段名description 代表字段的描述enum 是可选值,代表可选的 value。
3. 如果没有可提取的内容,忽略该字段。
4. 本次需提取的JSON Schema{{json}}
</字段说明>
<对话记录>
{{text}}
</对话记录>
`;
export const Prompt_CQJson = `我会给你几个问题类型请参考背景知识可能为空和对话记录判断我“本次问题”的类型并返回一个问题“类型ID”:
<问题类型>
{{typeList}}
</问题类型>
<背景知识>
{{systemPrompt}}
</背景知识>
<对话记录>
{{history}}
</对话记录>
Human"{{question}}"
类型ID=
`;

View File

@@ -12,16 +12,9 @@ export type CreateAppParams = {
export interface AppUpdateParams {
name?: string;
type?: `${AppTypeEnum}`;
simpleTemplateId?: string;
avatar?: string;
intro?: string;
modules?: AppSchema['modules'];
permission?: AppSchema['permission'];
teamTags?: AppSchema['teamTags'];
}
export type FormatForm2ModulesProps = {
formData: AppSimpleEditFormType;
chatModelMaxToken: number;
llmModelList: LLMModelItemType[];
};

View File

@@ -1,7 +1,12 @@
import type { AppTTSConfigType, ModuleItemType, VariableItemType } from '../module/type.d';
import type {
AppTTSConfigType,
FlowNodeTemplateType,
ModuleItemType,
VariableItemType
} from '../module/type.d';
import { AppTypeEnum } from './constants';
import { PermissionTypeEnum } from '../../support/permission/constant';
import type { AIChatModuleProps, DatasetModuleProps } from '../module/node/type.d';
import type { DatasetModuleProps } from '../module/node/type.d';
import { VariableInputEnum } from '../module/constants';
import { SelectedDatasetType } from '../module/api';
import { DatasetSearchModeEnum } from '../dataset/constants';
@@ -13,7 +18,6 @@ export interface AppSchema {
tmbId: string;
name: string;
type: `${AppTypeEnum}`;
simpleTemplateId: string;
avatar: string;
intro: string;
updateTime: number;
@@ -37,19 +41,6 @@ export type AppDetailType = AppSchema & {
canWrite: boolean;
};
// export type AppSimpleEditFormType = {
// aiSettings: AIChatModuleProps;
// dataset: DatasetModuleProps & {
// searchEmptyText: string;
// };
// userGuide: {
// welcomeText: string;
// variables: VariableItemType[];
// questionGuide: boolean;
// tts: AppTTSConfigType;
// };
// };
// Since useform cannot infer enumeration types, all enumeration keys can only be undone manually
export type AppSimpleEditFormType = {
// templateId: string;
aiSettings: {
@@ -58,8 +49,7 @@ export type AppSimpleEditFormType = {
temperature: number;
maxToken: number;
isResponseAnswerText: boolean;
quoteTemplate?: string | undefined;
quotePrompt?: string | undefined;
maxHistories: number;
};
dataset: {
datasets: SelectedDatasetType;
@@ -67,11 +57,11 @@ export type AppSimpleEditFormType = {
similarity?: number;
limit?: number;
usingReRank?: boolean;
searchEmptyText?: string;
datasetSearchUsingExtensionQuery?: boolean;
datasetSearchExtensionModel?: string;
datasetSearchExtensionBg?: string;
};
selectedTools: FlowNodeTemplateType[];
userGuide: {
welcomeText: string;
variables: {
@@ -94,34 +84,3 @@ export type AppSimpleEditFormType = {
};
};
};
/* simple mode template*/
export type AppSimpleEditConfigTemplateType = {
id: string;
name: string;
desc: string;
systemForm: {
aiSettings?: {
model?: boolean;
systemPrompt?: boolean;
temperature?: boolean;
maxToken?: boolean;
quoteTemplate?: boolean;
quotePrompt?: boolean;
};
dataset?: {
datasets?: boolean;
similarity?: boolean;
limit?: boolean;
searchMode: `${DatasetSearchModeEnum}`;
usingReRank: boolean;
searchEmptyText?: boolean;
};
userGuide?: {
welcomeText?: boolean;
variables?: boolean;
questionGuide?: boolean;
tts?: boolean;
};
};
};

View File

@@ -1,6 +1,10 @@
import type { AppSimpleEditFormType } from '../app/type';
import { FlowNodeTypeEnum } from '../module/node/constant';
import { ModuleOutputKeyEnum, ModuleInputKeyEnum } from '../module/constants';
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';
@@ -13,20 +17,19 @@ export const getDefaultAppForm = (): AppSimpleEditFormType => {
systemPrompt: '',
temperature: 0,
isResponseAnswerText: true,
quotePrompt: '',
quoteTemplate: '',
maxHistories: 6,
maxToken: 4000
},
dataset: {
datasets: [],
similarity: 0.4,
limit: 1500,
searchEmptyText: '',
searchMode: DatasetSearchModeEnum.embedding,
usingReRank: false,
datasetSearchUsingExtensionQuery: true,
datasetSearchExtensionBg: ''
},
selectedTools: [],
userGuide: {
welcomeText: '',
variables: [],
@@ -47,7 +50,10 @@ export const appModules2Form = ({ modules }: { modules: ModuleItemType[] }) => {
};
modules.forEach((module) => {
if (module.flowType === FlowNodeTypeEnum.chatNode) {
if (
module.flowType === FlowNodeTypeEnum.chatNode ||
module.flowType === FlowNodeTypeEnum.tools
) {
defaultAppForm.aiSettings.model = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.aiModel
@@ -64,13 +70,9 @@ export const appModules2Form = ({ modules }: { modules: ModuleItemType[] }) => {
module.inputs,
ModuleInputKeyEnum.aiChatMaxToken
);
defaultAppForm.aiSettings.quoteTemplate = findInputValueByKey(
defaultAppForm.aiSettings.maxHistories = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.aiChatQuoteTemplate
);
defaultAppForm.aiSettings.quotePrompt = findInputValueByKey(
module.inputs,
ModuleInputKeyEnum.aiChatQuotePrompt
ModuleInputKeyEnum.history
);
} else if (module.flowType === FlowNodeTypeEnum.datasetSearchNode) {
defaultAppForm.dataset.datasets = findInputValueByKey(
@@ -104,17 +106,6 @@ export const appModules2Form = ({ modules }: { modules: ModuleItemType[] }) => {
module.inputs,
ModuleInputKeyEnum.datasetSearchExtensionBg
);
// empty text
const emptyOutputs =
module.outputs.find((item) => item.key === ModuleOutputKeyEnum.datasetIsEmpty)?.targets ||
[];
const emptyOutput = emptyOutputs[0];
if (emptyOutput) {
const target = modules.find((item) => item.moduleId === emptyOutput.moduleId);
defaultAppForm.dataset.searchEmptyText =
target?.inputs?.find((item) => item.key === ModuleInputKeyEnum.answerText)?.value || '';
}
} else if (module.flowType === FlowNodeTypeEnum.userGuide) {
const { welcomeText, variableModules, questionGuide, ttsConfig } = splitGuideModule(
getGuideModule(modules)
@@ -125,6 +116,18 @@ export const appModules2Form = ({ modules }: { modules: ModuleItemType[] }) => {
questionGuide: questionGuide,
tts: ttsConfig
};
} else if (module.flowType === FlowNodeTypeEnum.pluginModule) {
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,
templateType: FlowNodeTemplateTypeEnum.other
});
}
});

View File

@@ -83,6 +83,7 @@ export const chats2GPTMessages = ({
});
}
} else {
//AI
item.value.forEach((value) => {
if (value.type === ChatItemValueTypeEnum.tool && value.tools && reserveTool) {
const tool_calls: ChatCompletionMessageToolCall[] = [];

View File

@@ -3,6 +3,8 @@ export type UpdateChatFeedbackProps = {
chatId: string;
chatItemId: string;
shareId?: string;
teamId?: string;
teamToken?: string;
outLinkUid?: string;
userBadFeedback?: string;
userGoodFeedback?: string;

View File

@@ -141,7 +141,7 @@ export type ChatHistoryItemResType = DispatchNodeResponseType & {
};
/* One tool run response */
export type ToolRunResponseItemType = Record<string, any> | Array;
export type ToolRunResponseItemType = any;
/* tool module response */
export type ToolModuleResponseItemType = {
id: string;

View File

@@ -154,8 +154,5 @@ export const SearchScoreTypeMap = {
}
};
export const FolderIcon = 'file/fill/folder';
export const FolderImgUrl = '/imgs/files/folder.svg';
export const CustomCollectionIcon = 'common/linkBlue';
export const LinkCollectionIcon = 'common/linkBlue';

View File

@@ -13,3 +13,10 @@ export type HttpQueryType = {
variables: Record<string, any>;
[key: string]: any;
};
/* http node */
export type HttpParamAndHeaderItemType = {
key: string;
type: string;
value: string;
};

View File

@@ -1,4 +1,4 @@
export enum ModuleTemplateTypeEnum {
export enum FlowNodeTemplateTypeEnum {
userGuide = 'userGuide',
systemInput = 'systemInput',
tools = 'tools',
@@ -87,7 +87,8 @@ export enum ModuleInputKeyEnum {
runAppSelectApp = 'app',
// plugin
pluginId = 'pluginId'
pluginId = 'pluginId',
pluginStart = 'pluginStart'
}
export enum ModuleOutputKeyEnum {
@@ -117,7 +118,10 @@ export enum ModuleOutputKeyEnum {
selectedTools = 'selectedTools',
// http
httpRawResponse = 'httpRawResponse'
httpRawResponse = 'httpRawResponse',
// plugin
pluginStart = 'pluginStart'
}
export enum VariableInputEnum {

View File

@@ -21,10 +21,12 @@ export enum FlowNodeInputTypeEnum {
// ai model select
selectLLMModel = 'selectLLMModel',
settingLLMModel = 'settingLLMModel',
// dataset special input
selectDataset = 'selectDataset',
selectDatasetParamsModal = 'selectDatasetParamsModal',
settingDatasetQuotePrompt = 'settingDatasetQuotePrompt',
hidden = 'hidden',
custom = 'custom'
@@ -57,7 +59,8 @@ export enum FlowNodeTypeEnum {
pluginInput = 'pluginInput',
pluginOutput = 'pluginOutput',
queryExtension = 'cfr',
tools = 'tools'
tools = 'tools',
stopTool = 'stopTool'
// abandon
}

View File

@@ -102,6 +102,13 @@ export type EditNodeFieldType = {
};
/* ------------- 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;

View File

@@ -90,6 +90,7 @@ export type DispatchNodeResponseType = {
// tool
toolCallTokens?: number;
toolDetail?: ChatHistoryItemResType[];
toolStop?: boolean;
};
export type DispatchNodeResultType<T> = {

View File

@@ -8,7 +8,9 @@ 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';
import { RunAppModule } from './system/runApp';
import { PluginInputModule } from './system/pluginInput';
@@ -16,11 +18,11 @@ import { PluginOutputModule } from './system/pluginOutput';
import { RunPluginModule } from './system/runPlugin';
import { AiQueryExtension } from './system/queryExtension';
import type { FlowModuleTemplateType, moduleTemplateListType } from '../../module/type.d';
import { ModuleTemplateTypeEnum } from '../../module/constants';
import type { FlowNodeTemplateType, moduleTemplateListType } from '../../module/type.d';
import { FlowNodeTemplateTypeEnum } from '../../module/constants';
/* app flow module templates */
export const appSystemModuleTemplates: FlowModuleTemplateType[] = [
export const appSystemModuleTemplates: FlowNodeTemplateType[] = [
UserGuideModule,
UserInputModule,
AiChatModule,
@@ -29,13 +31,14 @@ export const appSystemModuleTemplates: FlowModuleTemplateType[] = [
DatasetConcatModule,
RunAppModule,
ToolModule,
StopToolNode,
ClassifyQuestionModule,
ContextExtractModule,
HttpModule468,
AiQueryExtension
];
/* plugin flow module templates */
export const pluginSystemModuleTemplates: FlowModuleTemplateType[] = [
export const pluginSystemModuleTemplates: FlowNodeTemplateType[] = [
PluginInputModule,
PluginOutputModule,
AiChatModule,
@@ -44,6 +47,7 @@ export const pluginSystemModuleTemplates: FlowModuleTemplateType[] = [
DatasetConcatModule,
RunAppModule,
ToolModule,
StopToolNode,
ClassifyQuestionModule,
ContextExtractModule,
HttpModule468,
@@ -51,7 +55,7 @@ export const pluginSystemModuleTemplates: FlowModuleTemplateType[] = [
];
/* all module */
export const moduleTemplatesFlat: FlowModuleTemplateType[] = [
export const moduleTemplatesFlat: FlowNodeTemplateType[] = [
UserGuideModule,
UserInputModule,
AiChatModule,
@@ -63,6 +67,7 @@ export const moduleTemplatesFlat: FlowModuleTemplateType[] = [
HttpModule468,
HttpModule,
ToolModule,
StopToolNode,
AiChatModule,
RunAppModule,
PluginInputModule,
@@ -73,43 +78,43 @@ export const moduleTemplatesFlat: FlowModuleTemplateType[] = [
export const moduleTemplatesList: moduleTemplateListType = [
{
type: ModuleTemplateTypeEnum.userGuide,
label: 'core.module.template.Guide module',
type: FlowNodeTemplateTypeEnum.userGuide,
label: '',
list: []
},
{
type: ModuleTemplateTypeEnum.systemInput,
label: 'core.module.template.System input module',
list: []
},
{
type: ModuleTemplateTypeEnum.textAnswer,
type: FlowNodeTemplateTypeEnum.textAnswer,
label: 'core.module.template.Response module',
list: []
},
{
type: ModuleTemplateTypeEnum.functionCall,
type: FlowNodeTemplateTypeEnum.functionCall,
label: 'core.module.template.Function module',
list: []
},
{
type: ModuleTemplateTypeEnum.tools,
type: FlowNodeTemplateTypeEnum.tools,
label: 'core.module.template.Tool module',
list: []
},
{
type: ModuleTemplateTypeEnum.externalCall,
type: FlowNodeTemplateTypeEnum.externalCall,
label: 'core.module.template.External module',
list: []
},
{
type: ModuleTemplateTypeEnum.personalPlugin,
label: 'core.module.template.My plugin module',
type: FlowNodeTemplateTypeEnum.personalPlugin,
label: '',
list: []
},
{
type: ModuleTemplateTypeEnum.other,
type: FlowNodeTemplateTypeEnum.other,
label: '其他',
list: []
},
{
type: FlowNodeTemplateTypeEnum.systemInput,
label: 'core.module.template.System input module',
list: []
}
];

View File

@@ -59,7 +59,7 @@ export const Input_Template_DynamicInput: FlowNodeInputItemType = {
hideInApp: true
};
export const Input_Template_AiModel: FlowNodeInputItemType = {
export const Input_Template_SelectAIModel: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.aiModel,
type: FlowNodeInputTypeEnum.selectLLMModel,
label: 'core.module.input.label.aiModel',
@@ -68,6 +68,15 @@ export const Input_Template_AiModel: FlowNodeInputItemType = {
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,
@@ -83,7 +92,7 @@ export const Input_Template_System_Prompt: FlowNodeInputItemType = {
export const Input_Template_Dataset_Quote: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.aiChatDatasetQuote,
type: FlowNodeInputTypeEnum.target,
type: FlowNodeInputTypeEnum.settingDatasetQuotePrompt,
label: '知识库引用',
description: 'core.module.Dataset quote.Input description',
valueType: ModuleIOValueTypeEnum.datasetQuote,

View File

@@ -3,11 +3,11 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../../node/constant';
import { FlowModuleTemplateType } from '../../../type';
import { FlowNodeTemplateType } from '../../../type';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleTemplateTypeEnum
FlowNodeTemplateTypeEnum
} from '../../../constants';
import {
Input_Template_AddInputParam,
@@ -16,9 +16,9 @@ import {
} from '../../input';
import { Output_Template_AddOutput, Output_Template_Finish } from '../../output';
export const HttpModule: FlowModuleTemplateType = {
export const HttpModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.httpRequest,
templateType: ModuleTemplateTypeEnum.externalCall,
templateType: FlowNodeTemplateTypeEnum.externalCall,
flowType: FlowNodeTypeEnum.httpRequest,
avatar: '/imgs/module/http.png',
name: 'core.module.template.Http request',

View File

@@ -3,15 +3,15 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum
FlowNodeTemplateTypeEnum
} from '../../constants';
import {
Input_Template_AiModel,
Input_Template_SettingAiModel,
Input_Template_Dataset_Quote,
Input_Template_History,
Input_Template_Switch,
@@ -21,18 +21,18 @@ import {
import { chatNodeSystemPromptTip } from '../tip';
import { Output_Template_Finish, Output_Template_UserChatInput } from '../output';
export const AiChatModule: FlowModuleTemplateType = {
export const AiChatModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.chatNode,
templateType: ModuleTemplateTypeEnum.textAnswer,
templateType: FlowNodeTemplateTypeEnum.textAnswer,
flowType: FlowNodeTypeEnum.chatNode,
avatar: '/imgs/module/AI.png',
name: 'AI 对话',
intro: 'AI 大模型对话',
showStatus: true,
// isTool: true,
isTool: true,
inputs: [
Input_Template_Switch,
Input_Template_AiModel,
Input_Template_SettingAiModel,
// --- settings modal
{
key: ModuleInputKeyEnum.aiChatTemperature,
@@ -83,14 +83,6 @@ export const AiChatModule: FlowModuleTemplateType = {
showTargetInApp: false,
showTargetInPlugin: false
},
{
key: ModuleInputKeyEnum.aiChatSettingModal,
type: FlowNodeInputTypeEnum.aiSettings,
label: '',
valueType: ModuleIOValueTypeEnum.any,
showTargetInApp: false,
showTargetInPlugin: false
},
// settings modal ---
{
...Input_Template_System_Prompt,

View File

@@ -1,12 +1,16 @@
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import { ModuleIOValueTypeEnum, ModuleInputKeyEnum, ModuleTemplateTypeEnum } from '../../constants';
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: FlowModuleTemplateType = {
export const AssignedAnswerModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.answerNode,
templateType: ModuleTemplateTypeEnum.textAnswer,
templateType: FlowNodeTemplateTypeEnum.textAnswer,
flowType: FlowNodeTypeEnum.answerNode,
avatar: '/imgs/module/reply.png',
name: '指定回复',

View File

@@ -3,10 +3,14 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import { ModuleIOValueTypeEnum, ModuleInputKeyEnum, ModuleTemplateTypeEnum } from '../../constants';
import { FlowNodeTemplateType } from '../../type.d';
import {
Input_Template_AiModel,
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import {
Input_Template_SelectAIModel,
Input_Template_History,
Input_Template_Switch,
Input_Template_UserChatInput
@@ -15,9 +19,9 @@ import { Output_Template_UserChatInput } from '../output';
import { Input_Template_System_Prompt } from '../input';
import { LLMModelTypeEnum } from '../../../ai/constants';
export const ClassifyQuestionModule: FlowModuleTemplateType = {
export const ClassifyQuestionModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.classifyQuestion,
templateType: ModuleTemplateTypeEnum.functionCall,
templateType: FlowNodeTemplateTypeEnum.functionCall,
flowType: FlowNodeTypeEnum.classifyQuestion,
avatar: '/imgs/module/cq.png',
name: '问题分类',
@@ -26,7 +30,7 @@ export const ClassifyQuestionModule: FlowModuleTemplateType = {
inputs: [
Input_Template_Switch,
{
...Input_Template_AiModel,
...Input_Template_SelectAIModel,
llmModelType: LLMModelTypeEnum.classify
},
{

View File

@@ -3,19 +3,23 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_AiModel, Input_Template_History, Input_Template_Switch } from '../input';
import {
Input_Template_SelectAIModel,
Input_Template_History,
Input_Template_Switch
} from '../input';
import { LLMModelTypeEnum } from '../../../ai/constants';
export const ContextExtractModule: FlowModuleTemplateType = {
export const ContextExtractModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.contentExtract,
templateType: ModuleTemplateTypeEnum.functionCall,
templateType: FlowNodeTemplateTypeEnum.functionCall,
flowType: FlowNodeTypeEnum.contentExtract,
avatar: '/imgs/module/extract.png',
name: '文本内容提取',
@@ -25,7 +29,7 @@ export const ContextExtractModule: FlowModuleTemplateType = {
inputs: [
Input_Template_Switch,
{
...Input_Template_AiModel,
...Input_Template_SelectAIModel,
llmModelType: LLMModelTypeEnum.extractFields
},
{
@@ -35,7 +39,6 @@ export const ContextExtractModule: FlowModuleTemplateType = {
label: '提取要求描述',
description:
'给AI一些对应的背景知识或要求描述引导AI更好的完成任务。\n该输入框可使用全局变量。',
required: true,
placeholder:
'例如: \n1. 当前时间为: {{cTime}}。你是一个实验室预约助手,你的任务是帮助用户预约实验室,从文本中获取对应的预约信息。\n2. 你是谷歌搜索助手,需要从文本中提取出合适的搜索词。',
showTargetInApp: true,

View File

@@ -3,12 +3,12 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_Dataset_Quote, Input_Template_Switch } from '../input';
import { Output_Template_Finish } from '../output';
@@ -20,10 +20,10 @@ export const getOneQuoteInputTemplate = (key = getNanoid()) => ({
type: FlowNodeInputTypeEnum.hidden
});
export const DatasetConcatModule: FlowModuleTemplateType = {
export const DatasetConcatModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.datasetConcatNode,
flowType: FlowNodeTypeEnum.datasetConcatNode,
templateType: ModuleTemplateTypeEnum.tools,
templateType: FlowNodeTemplateTypeEnum.other,
avatar: '/imgs/module/concat.svg',
name: '知识库搜索引用合并',
intro: '可以将多个知识库搜索结果进行合并输出。使用 RRF 的合并方式进行最终排序输出。',

View File

@@ -3,20 +3,20 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum
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 DatasetSearchModule: FlowModuleTemplateType = {
export const DatasetSearchModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.datasetSearchNode,
templateType: ModuleTemplateTypeEnum.functionCall,
templateType: FlowNodeTemplateTypeEnum.functionCall,
flowType: FlowNodeTypeEnum.datasetSearchNode,
avatar: '/imgs/module/db.png',
name: '知识库搜索',

View File

@@ -3,12 +3,12 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowModuleTemplateType } from '../../type';
import { FlowNodeTemplateType } from '../../type';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum
FlowNodeTemplateTypeEnum
} from '../../constants';
import {
Input_Template_AddInputParam,
@@ -17,9 +17,9 @@ import {
} from '../input';
import { Output_Template_AddOutput, Output_Template_Finish } from '../output';
export const HttpModule468: FlowModuleTemplateType = {
export const HttpModule468: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.httpRequest468,
templateType: ModuleTemplateTypeEnum.externalCall,
templateType: FlowNodeTemplateTypeEnum.externalCall,
flowType: FlowNodeTypeEnum.httpRequest468,
avatar: '/imgs/module/http.png',
name: 'HTTP 请求',

View File

@@ -1,15 +1,43 @@
import { ModuleTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import {
FlowNodeTemplateTypeEnum,
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum
} from '../../constants';
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
export const PluginInputModule: FlowModuleTemplateType = {
export const PluginInputModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.pluginInput,
templateType: ModuleTemplateTypeEnum.systemInput,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowType: FlowNodeTypeEnum.pluginInput,
avatar: '/imgs/module/input.png',
name: '定义插件输入',
intro: '自定义配置外部输入,使用插件时,仅暴露自定义配置的输入',
showStatus: false,
inputs: [],
outputs: []
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,10 +1,10 @@
import { ModuleTemplateTypeEnum } from '../../constants';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type.d';
export const PluginOutputModule: FlowModuleTemplateType = {
export const PluginOutputModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.pluginOutput,
templateType: ModuleTemplateTypeEnum.systemInput,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowType: FlowNodeTypeEnum.pluginOutput,
avatar: '/imgs/module/output.png',
name: '定义插件输出',

View File

@@ -3,25 +3,25 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowModuleTemplateType } from '../../type';
import { FlowNodeTemplateType } from '../../type';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum
FlowNodeTemplateTypeEnum
} from '../../constants';
import {
Input_Template_History,
Input_Template_Switch,
Input_Template_UserChatInput,
Input_Template_AiModel
Input_Template_SelectAIModel
} from '../input';
import { Output_Template_UserChatInput } from '../output';
import { LLMModelTypeEnum } from '../../../ai/constants';
export const AiQueryExtension: FlowModuleTemplateType = {
export const AiQueryExtension: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.chatNode,
templateType: ModuleTemplateTypeEnum.other,
templateType: FlowNodeTemplateTypeEnum.other,
flowType: FlowNodeTypeEnum.queryExtension,
avatar: '/imgs/module/cfr.svg',
name: '问题优化',
@@ -31,7 +31,7 @@ export const AiQueryExtension: FlowModuleTemplateType = {
inputs: [
Input_Template_Switch,
{
...Input_Template_AiModel,
...Input_Template_SelectAIModel,
llmModelType: LLMModelTypeEnum.queryExtension
},
{

View File

@@ -3,12 +3,12 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum
FlowNodeTemplateTypeEnum
} from '../../constants';
import {
Input_Template_History,
@@ -17,9 +17,9 @@ import {
} from '../input';
import { Output_Template_Finish, Output_Template_UserChatInput } from '../output';
export const RunAppModule: FlowModuleTemplateType = {
export const RunAppModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.runApp,
templateType: ModuleTemplateTypeEnum.externalCall,
templateType: FlowNodeTemplateTypeEnum.externalCall,
flowType: FlowNodeTypeEnum.runApp,
avatar: '/imgs/module/app.png',
name: '应用调用',

View File

@@ -1,10 +1,10 @@
import { ModuleTemplateTypeEnum } from '../../constants';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type.d';
export const RunPluginModule: FlowModuleTemplateType = {
export const RunPluginModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.pluginModule,
templateType: ModuleTemplateTypeEnum.externalCall,
templateType: FlowNodeTemplateTypeEnum.externalCall,
flowType: FlowNodeTypeEnum.pluginModule,
intro: '',
name: '',

View File

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

View File

@@ -1,12 +1,17 @@
import { FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum
FlowNodeTemplateTypeEnum,
ModuleInputKeyEnum
} from '../../constants';
import {
Input_Template_AiModel,
Input_Template_SettingAiModel,
Input_Template_History,
Input_Template_Switch,
Input_Template_System_Prompt,
@@ -16,19 +21,43 @@ import { chatNodeSystemPromptTip } from '../tip';
import { Output_Template_Finish, Output_Template_UserChatInput } from '../output';
import { LLMModelTypeEnum } from '../../../ai/constants';
export const ToolModule: FlowModuleTemplateType = {
export const ToolModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.tools,
flowType: FlowNodeTypeEnum.tools,
templateType: ModuleTemplateTypeEnum.functionCall,
templateType: FlowNodeTemplateTypeEnum.functionCall,
avatar: '/imgs/module/tool.svg',
name: '工具调用(实验)',
intro: '通过AI模型自动选择一个或多个工具进行调用。工具可以是其他功能块或插件。',
intro: '通过AI模型自动选择一个或多个功能块进行调用,也可以对插件进行调用。',
showStatus: true,
inputs: [
Input_Template_Switch,
{
...Input_Template_AiModel,
llmModelType: LLMModelTypeEnum.toolCall
...Input_Template_SettingAiModel,
llmModelType: LLMModelTypeEnum.all
},
{
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
},
{
...Input_Template_System_Prompt,

View File

@@ -1,11 +1,15 @@
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type.d';
import { userGuideTip } from '../tip';
import { ModuleIOValueTypeEnum, ModuleInputKeyEnum, ModuleTemplateTypeEnum } from '../../constants';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
export const UserGuideModule: FlowModuleTemplateType = {
export const UserGuideModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.userGuide,
templateType: ModuleTemplateTypeEnum.userGuide,
templateType: FlowNodeTemplateTypeEnum.userGuide,
flowType: FlowNodeTypeEnum.userGuide,
avatar: '/imgs/module/userGuide.png',
name: '全局配置',

View File

@@ -3,17 +3,17 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import { FlowNodeTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum
FlowNodeTemplateTypeEnum
} from '../../constants';
export const UserInputModule: FlowModuleTemplateType = {
export const UserInputModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.questionInput,
templateType: ModuleTemplateTypeEnum.systemInput,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowType: FlowNodeTypeEnum.questionInput,
avatar: '/imgs/module/userChatInput.svg',
name: '对话入口',

View File

@@ -2,7 +2,7 @@ import { FlowNodeTypeEnum } from './node/constant';
import {
ModuleIOValueTypeEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum,
FlowNodeTemplateTypeEnum,
VariableInputEnum
} from './constants';
import { DispatchNodeResponseKeyEnum } from './runtime/constants';
@@ -15,10 +15,11 @@ import {
} from '../chat/type';
import { ChatNodeUsageType } from '../../support/wallet/bill/type';
import { RunningModuleItemType } from './runtime/type';
import { PluginTypeEnum } from 'core/plugin/constants';
export type FlowModuleTemplateType = {
export type FlowNodeTemplateType = {
id: string; // module id, unique
templateType: `${ModuleTemplateTypeEnum}`;
templateType: `${FlowNodeTemplateTypeEnum}`;
flowType: `${FlowNodeTypeEnum}`; // render node card
avatar?: string;
name: string;
@@ -27,14 +28,18 @@ export type FlowModuleTemplateType = {
showStatus?: boolean; // chatting response step status
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
// plugin data
pluginType?: `${PluginTypeEnum}`;
parentId?: string;
};
export type FlowModuleItemType = FlowModuleTemplateType & {
export type FlowModuleItemType = FlowNodeTemplateType & {
moduleId: string;
};
export type moduleTemplateListType = {
type: `${ModuleTemplateTypeEnum}`;
type: `${FlowNodeTemplateTypeEnum}`;
label: string;
list: FlowModuleTemplateType[];
list: FlowNodeTemplateType[];
}[];
// store module type

View File

@@ -9,6 +9,7 @@ import { FlowNodeInputItemType, FlowNodeOutputItemType } from './node/type';
import { AppTTSConfigType, ModuleItemType, VariableItemType } from './type';
import { Input_Template_Switch } from './template/input';
import { EditorVariablePickerType } from '../../../web/components/common/Textarea/PromptEditor/type';
import { Output_Template_Finish } from './template/output';
/* module */
export const getGuideModule = (modules: ModuleItemType[]) =>
@@ -92,13 +93,16 @@ export const plugin2ModuleIO = (
connected: false
}))
]
: [],
: [Input_Template_Switch],
outputs: pluginOutput
? pluginOutput.outputs.map((item) => ({
...item,
edit: false
}))
: []
? [
...pluginOutput.outputs.map((item) => ({
...item,
edit: false
})),
Output_Template_Finish
]
: [Output_Template_Finish]
};
};

View File

@@ -27,6 +27,26 @@ export const defaultModules: ModuleItemType[] = [
}
];
export enum PluginTypeEnum {
folder = 'folder',
custom = 'custom',
http = 'http'
}
export const pluginTypeMap = {
[PluginTypeEnum.folder]: {
label: '文件夹',
icon: 'file/fill/folder'
},
[PluginTypeEnum.custom]: {
label: '自定义',
icon: 'common/custom'
},
[PluginTypeEnum.http]: {
label: 'HTTP',
icon: 'common/http'
}
};
export enum PluginSourceEnum {
personal = 'personal',
community = 'community',

View File

@@ -1,21 +1,40 @@
import type { ModuleItemType } from '../module/type.d';
import { PluginTypeEnum } from './constants';
import { HttpAuthMethodType } from './httpPlugin/type';
export type CreateOnePluginParams = {
name: string;
avatar: string;
intro: string;
modules?: ModuleItemType[];
modules: ModuleItemType[];
parentId: string | null;
type: `${PluginTypeEnum}`;
metadata?: {
apiSchemaStr?: string;
customHeaders?: string;
};
};
export type UpdatePluginParams = {
id: string;
parentId?: string | null;
name?: string;
avatar?: string;
intro?: string;
modules?: ModuleItemType[];
metadata?: {
apiSchemaStr?: string;
customHeaders?: string;
};
};
export type PluginListItemType = {
_id: string;
parentId: string;
type: `${PluginTypeEnum}`;
name: string;
avatar: string;
intro: string;
metadata?: {
apiSchemaStr?: string;
customHeaders?: string;
};
};

View File

@@ -0,0 +1,13 @@
export type PathDataType = {
name: string;
description: string;
method: string;
path: string;
params: any[];
request: any;
};
export type OpenApiJsonSchema = {
pathData: PathDataType[];
serverPath: string;
};

View File

@@ -0,0 +1,516 @@
import { getNanoid } from '../../../common/string/tools';
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 { CreateOnePluginParams } from '../controller';
import { ModuleItemType } from '../../module/type';
import { HttpImgUrl } from '../../../common/file/image/constants';
export const str2OpenApiSchema = (yamlStr = ''): OpenApiJsonSchema => {
try {
const data: OpenAPIV3.Document = (() => {
try {
return JSON.parse(yamlStr);
} catch (jsonError) {
return yaml.load(yamlStr, { schema: yaml.FAILSAFE_SCHEMA });
}
})();
const serverPath = data.servers?.[0].url || '';
const pathData = Object.keys(data.paths)
.map((path) => {
const methodData: any = data.paths[path];
return Object.keys(methodData)
.filter((method) =>
['get', 'post', 'put', 'delete', 'patch'].includes(method.toLocaleLowerCase())
)
.map((method) => {
const methodInfo = methodData[method];
if (methodInfo.deprecated) return;
const result = {
path,
method,
name: methodInfo.operationId || path,
description: methodInfo.description,
params: methodInfo.parameters,
request: methodInfo?.requestBody
};
return result;
});
})
.flat()
.filter(Boolean) as OpenApiJsonSchema['pathData'];
return { pathData, serverPath };
} catch (err) {
throw new Error('Invalid Schema');
}
};
export const httpApiSchema2Plugins = ({
parentId,
apiSchemaStr = '',
customHeader = ''
}: {
parentId: string;
apiSchemaStr?: string;
customHeader?: string;
}): CreateOnePluginParams[] => {
const jsonSchema = str2OpenApiSchema(apiSchemaStr);
const baseUrl = jsonSchema.serverPath;
return jsonSchema.pathData.map((item) => {
const pluginOutputId = getNanoid();
const httpId = getNanoid();
const pluginOutputKey = 'result';
const properties = item.request?.content?.['application/json']?.schema?.properties;
const propsKeys = properties ? Object.keys(properties) : [];
const pluginInputs: FlowNodeInputItemType[] = [
...(item.params?.map((param: any) => {
return {
key: param.name,
valueType: ModuleIOValueTypeEnum.string,
label: param.name,
type: FlowNodeInputTypeEnum.target,
required: param.required,
description: param.description,
edit: true,
editField: {
key: true,
name: true,
description: true,
required: true,
dataType: true,
inputType: true,
isToolInput: true
},
connected: true,
toolDescription: param.description
};
}) || []),
...(propsKeys?.map((key) => {
const prop = properties[key];
return {
key,
valueType: ModuleIOValueTypeEnum.string,
label: key,
type: FlowNodeInputTypeEnum.target,
required: false,
description: prop.description,
edit: true,
editField: {
key: true,
name: true,
description: true,
required: true,
dataType: true,
inputType: true,
isToolInput: true
},
connected: true,
toolDescription: prop.description
};
}) || [])
];
const pluginOutputs: FlowNodeOutputItemType[] = [
...(item.params?.map((param: any) => {
return {
key: param.name,
valueType: ModuleIOValueTypeEnum.string,
label: param.name,
type: FlowNodeOutputTypeEnum.source,
edit: true,
targets: [
{
moduleId: httpId,
key: param.name
}
]
};
}) || []),
...(propsKeys?.map((key) => {
return {
key,
valueType: ModuleIOValueTypeEnum.string,
label: key,
type: FlowNodeOutputTypeEnum.source,
edit: true,
targets: [
{
moduleId: httpId,
key
}
]
};
}) || [])
];
const httpInputs: FlowNodeInputItemType[] = [
...(item.params?.map((param: any) => {
return {
key: param.name,
valueType: ModuleIOValueTypeEnum.string,
label: param.name,
type: FlowNodeInputTypeEnum.target,
description: param.description,
edit: true,
editField: {
key: true,
description: true,
dataType: true
},
connected: true
};
}) || []),
...(propsKeys?.map((key) => {
const prop = properties[key];
return {
key,
valueType: ModuleIOValueTypeEnum.string,
label: key,
type: FlowNodeInputTypeEnum.target,
description: prop.description,
edit: true,
editField: {
key: true,
description: true,
dataType: true
},
connected: true
};
}) || [])
];
/* http node setting */
const httpNodeParams: HttpParamAndHeaderItemType[] = [];
const httpNodeHeaders: HttpParamAndHeaderItemType[] = [];
let httpNodeBody = '{}';
const requestUrl = `${baseUrl}${item.path}`;
if (item.params && item.params.length > 0) {
for (const param of item.params) {
if (param.in === 'header') {
httpNodeHeaders.push({
key: param.name,
type: param.schema?.type || ModuleIOValueTypeEnum.string,
value: `{{${param.name}}}`
});
} else if (param.in === 'body') {
httpNodeBody = JSON.stringify(
{ ...JSON.parse(httpNodeBody), [param.name]: `{{${param.name}}}` },
null,
2
);
} else if (param.in === 'query') {
httpNodeParams.push({
key: param.name,
type: param.schema?.type || ModuleIOValueTypeEnum.string,
value: `{{${param.name}}}`
});
}
}
}
if (item.request) {
const properties = item.request?.content?.['application/json']?.schema?.properties;
const keys = Object.keys(properties);
if (keys.length > 0) {
httpNodeBody = JSON.stringify(
keys.reduce((acc: any, key) => {
acc[key] = `{{${key}}}`;
return acc;
}, {}),
null,
2
);
}
}
if (customHeader) {
const headersObj = (() => {
try {
return JSON.parse(customHeader) as Record<string, string>;
} catch (err) {
return {};
}
})();
for (const key in headersObj) {
httpNodeHeaders.push({
key,
type: 'string',
// @ts-ignore
value: headersObj[key]
});
}
}
/* Combine complete modules */
const modules: ModuleItemType[] = [
{
moduleId: getNanoid(),
name: PluginInputModule.name,
intro: PluginInputModule.intro,
avatar: PluginInputModule.avatar,
flowType: PluginInputModule.flowType,
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
]
},
{
moduleId: pluginOutputId,
name: PluginOutputModule.name,
intro: PluginOutputModule.intro,
avatar: PluginOutputModule.avatar,
flowType: PluginOutputModule.flowType,
showStatus: PluginOutputModule.showStatus,
position: {
x: 1607.7142331269126,
y: -151.8669210746189
},
inputs: [
{
key: pluginOutputKey,
valueType: 'string',
label: pluginOutputKey,
type: 'target',
required: true,
description: '',
edit: true,
editField: {
key: true,
name: true,
description: true,
required: false,
dataType: true,
inputType: false
},
connected: true
}
],
outputs: [
{
key: pluginOutputKey,
valueType: 'string',
label: pluginOutputKey,
type: 'source',
edit: true,
targets: []
}
]
},
{
moduleId: httpId,
name: HttpModule468.name,
intro: HttpModule468.intro,
avatar: HttpModule468.avatar,
flowType: HttpModule468.flowType,
showStatus: true,
position: {
x: 1042.549746602742,
y: -447.77496332641647
},
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: 'system_httpMethod',
type: 'custom',
valueType: 'string',
label: '',
value: item.method.toUpperCase(),
required: true,
showTargetInApp: false,
showTargetInPlugin: false,
connected: false
},
{
key: 'system_httpReqUrl',
type: 'hidden',
valueType: '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
},
{
key: 'system_httpHeader',
type: 'custom',
valueType: '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
},
{
key: 'system_httpParams',
type: 'hidden',
valueType: 'any',
value: httpNodeParams,
label: '',
required: false,
showTargetInApp: false,
showTargetInPlugin: false,
connected: false
},
{
key: 'system_httpJsonBody',
type: 'hidden',
valueType: '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'
}
}
]
}
];
return {
name: item.name,
avatar: HttpImgUrl,
intro: item.description,
parentId,
type: PluginTypeEnum.http,
modules
};
});
};

View File

@@ -1,6 +1,7 @@
import { ModuleTemplateTypeEnum } from 'core/module/constants';
import type { FlowModuleTemplateType, ModuleItemType } from '../module/type.d';
import { PluginSourceEnum } from './constants';
import { PluginSourceEnum, PluginTypeEnum } from './constants';
import { MethodType } from './controller';
export type PluginItemSchema = {
_id: string;
@@ -12,6 +13,13 @@ export type PluginItemSchema = {
intro: string;
updateTime: Date;
modules: ModuleItemType[];
parentId: string;
type: `${PluginTypeEnum}`;
metadata?: {
pluginUid?: string;
apiSchemaStr?: string;
customHeaders?: string;
};
};
/* plugin template */
@@ -19,7 +27,7 @@ export type PluginTemplateType = PluginRuntimeType & {
author?: string;
id: string;
source: `${PluginSourceEnum}`;
templateType: FlowModuleTemplateType['templateType'];
templateType: FlowNodeTemplateType['templateType'];
intro: string;
modules: ModuleItemType[];
};
@@ -29,5 +37,6 @@ export type PluginRuntimeType = {
name: string;
avatar: string;
showStatus?: boolean;
isTool?: boolean;
modules: ModuleItemType[];
};

View File

@@ -6,11 +6,15 @@
"dayjs": "^1.11.7",
"encoding": "^0.1.13",
"js-tiktoken": "^1.0.7",
"openapi-types": "^12.1.3",
"openai": "4.28.0",
"nanoid": "^4.0.1",
"timezones-list": "^3.0.2"
"js-yaml": "^4.1.0",
"timezones-list": "^3.0.2",
"next": "13.5.2"
},
"devDependencies": {
"@types/js-yaml": "^4.0.9",
"@types/node": "^20.8.5"
}
}