Commit d682a825 by Archer Committed by GitHub

4.8.9 test (#2299)

* perf: read file prompt

* perf: read file prompt

* perf: free plan tip

* feat: cron job usage

* perf: app templates

* perf: get llm model by name

* feat: support outlink upload file

* fix: upload limit
parent c6dd3076
export const getLLMModel = (model?: string) => {
return global.llmModels.find((item) => item.model === model) ?? global.llmModels[0];
return (
global.llmModels.find((item) => item.model === model || item.name === model) ??
global.llmModels[0]
);
};
export const getDatasetModel = (model?: string) => {
return (
global.llmModels?.filter((item) => item.datasetProcess)?.find((item) => item.model === model) ??
global.llmModels[0]
global.llmModels
?.filter((item) => item.datasetProcess)
?.find((item) => item.model === model || item.name === model) ?? global.llmModels[0]
);
};
export const getVectorModel = (model?: string) => {
return global.vectorModels.find((item) => item.model === model) || global.vectorModels[0];
return (
global.vectorModels.find((item) => item.model === model || item.name === model) ||
global.vectorModels[0]
);
};
export function getAudioSpeechModel(model?: string) {
return (
global.audioSpeechModels.find((item) => item.model === model) || global.audioSpeechModels[0]
global.audioSpeechModels.find((item) => item.model === model || item.name === model) ||
global.audioSpeechModels[0]
);
}
......
......@@ -95,7 +95,7 @@ export const dispatchReadFiles = async (props: Props): Promise<Response> => {
})
.filter(Boolean)
.slice(0, maxFiles);
console.log(parseUrlList);
const readFilesResult = await Promise.all(
parseUrlList
.map(async (url) => {
......
<svg width="100%" height="100%" viewBox="0 0 89 32" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M52.308 3.07812H57.8465V4.92428H56.0003V6.77043H54.1541V10.4627H57.8465V12.3089H54.1541V25.232H52.308V27.0781H46.7695V25.232H48.6157V12.3089H46.7695V10.4627H48.6157V6.77043H50.4618V4.92428H52.308V3.07812Z" fill="currentColor"></path><path d="M79.3849 23.3858H81.2311V25.232H83.0772V27.0781H88.6157V25.232H86.7695V23.3858H84.9234V4.92428H79.3849V23.3858Z" fill="currentColor"></path><path d="M57.8465 14.155H59.6926V12.3089H61.5388V10.4627H70.7695V12.3089H74.4618V23.3858H76.308V25.232H78.1541V27.0781H72.6157V25.232H70.7695V23.3858H68.9234V14.155H67.0772V12.3089H65.2311V14.155H63.3849V23.3858H65.2311V25.232H67.0772V27.0781H61.5388V25.232H59.6926V23.3858H57.8465V14.155Z" fill="currentColor"></path><path d="M67.0772 25.232V23.3858H68.9234V25.232H67.0772Z" fill="currentColor"></path><rect opacity="0.22" x="7.38477" y="29.5391" width="2.46154" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.85" x="2.46094" y="19.6914" width="12.3077" height="2.46154" fill="#5F4CD9"></rect><rect x="4.92383" y="17.2305" width="9.84615" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.4" x="7.38477" y="27.0781" width="4.92308" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.7" y="22.1562" width="14.7692" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.5" x="7.38477" y="24.6133" width="7.38462" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.22" x="7.38477" y="12.3086" width="2.46154" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.85" x="2.46094" y="2.46094" width="12.3077" height="2.46154" fill="#5F4CD9"></rect><rect x="4.92383" width="9.84615" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.4" x="7.38477" y="9.84375" width="4.92308" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.7" y="4.92188" width="14.7692" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.5" x="7.38477" y="7.38281" width="7.38462" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.22" x="24.6152" y="29.5391" width="2.46154" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.85" x="19.6914" y="19.6914" width="12.3077" height="2.46154" fill="#5F4CD9"></rect><rect x="22.1543" y="17.2305" width="9.84615" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.4" x="24.6152" y="27.0781" width="4.92308" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.7" x="17.2305" y="22.1562" width="14.7692" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.5" x="24.6152" y="24.6133" width="7.38462" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.22" x="24.6152" y="12.3086" width="2.46154" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.85" x="19.6914" y="2.46094" width="12.3077" height="2.46154" fill="#5F4CD9"></rect><rect x="22.1543" width="9.84615" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.4" x="24.6152" y="9.84375" width="4.92308" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.7" x="17.2305" y="4.92188" width="14.7692" height="2.46154" fill="#5F4CD9"></rect><rect opacity="0.5" x="24.6152" y="7.38281" width="7.38462" height="2.46154" fill="#5F4CD9"></rect></svg>
\ No newline at end of file
......@@ -20,6 +20,7 @@ import { getDocPath } from '@/web/common/system/doc';
import AIModelSelector from '@/components/Select/AIModelSelector';
import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import { getWebLLMModel } from '@/web/common/system/utils';
const AIChatSettingsModal = ({
onClose,
......@@ -44,18 +45,18 @@ const AIChatSettingsModal = ({
const showVisionSwitch = watch(NodeInputKeyEnum.aiChatVision) !== undefined;
const showMaxHistoriesSlider = watch('maxHistories') !== undefined;
const useVision = watch('aiChatVision');
const selectedModel = llmModelList.find((item) => item.model === model) || llmModelList[0];
const selectedModel = getWebLLMModel(model);
const llmSupportVision = !!selectedModel?.vision;
const tokenLimit = useMemo(() => {
return llmModelList.find((item) => item.model === model)?.maxResponse || 4096;
}, [llmModelList, model]);
return selectedModel?.maxResponse || 4096;
}, [selectedModel?.maxResponse]);
const onChangeModel = (e: string) => {
setValue('model', e);
// update max tokens
const modelData = llmModelList.find((item) => item.model === e);
const modelData = getWebLLMModel(e);
if (modelData) {
setValue('maxToken', modelData.maxResponse / 2);
}
......
......@@ -137,6 +137,7 @@ const ChatInput = ({
const { previewUrl } = await uploadFile2DB({
file: copyFile.rawFile,
bucketName: 'chat',
outLinkAuthData,
metadata: {
chatId
},
......@@ -168,7 +169,7 @@ const ChatInput = ({
{
manual: false,
errorToast: t('common:upload_file_error'),
refreshDeps: [fileList]
refreshDeps: [fileList, outLinkAuthData, chatId]
}
);
const onSelectFile = useCallback(
......
......@@ -7,6 +7,7 @@ import {
import { useTranslation } from 'next-i18next';
import React, { useMemo } from 'react';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { getWebLLMModel } from '@/web/common/system/utils';
const SearchParamsTip = ({
searchMode,
......@@ -34,11 +35,8 @@ const SearchParamsTip = ({
const extensionModelName = useMemo(
() =>
datasetSearchUsingExtensionQuery
? llmModelList.find((item) => item.model === queryExtensionModel)?.name ??
llmModelList[0]?.name
: undefined,
[datasetSearchUsingExtensionQuery, llmModelList, queryExtensionModel]
datasetSearchUsingExtensionQuery ? getWebLLMModel(queryExtensionModel)?.name : undefined,
[datasetSearchUsingExtensionQuery, queryExtensionModel, llmModelList]
);
return (
......
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { uploadFile } from '@fastgpt/service/common/file/gridfs/controller';
import { getUploadModel } from '@fastgpt/service/common/file/multer';
import { removeFilesByPaths } from '@fastgpt/service/common/file/utils';
......@@ -10,6 +9,7 @@ import { ReadFileBaseUrl } from '@fastgpt/global/common/file/constants';
import { addLog } from '@fastgpt/service/common/system/log';
import { authFrequencyLimit } from '@/service/common/frequencyLimit/api';
import { addSeconds } from 'date-fns';
import { authChatCert } from '@/service/support/permission/auth/chat';
const authUploadLimit = (tmbId: string) => {
if (!global.feConfigs.uploadFileMaxAmount) return;
......@@ -21,19 +21,18 @@ const authUploadLimit = (tmbId: string) => {
};
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
const start = Date.now();
/* Creates the multer uploader */
const upload = getUploadModel({
maxSize: (global.feConfigs?.uploadFileMaxSize || 500) * 1024 * 1024
});
const filePaths: string[] = [];
try {
const { teamId, tmbId } = await authCert({ req, authToken: true });
const start = Date.now();
/* Creates the multer uploader */
const upload = getUploadModel({
maxSize: (global.feConfigs?.uploadFileMaxSize || 500) * 1024 * 1024
});
const { file, bucketName, metadata } = await upload.doUpload(req, res);
await authUploadLimit(tmbId);
const { teamId, tmbId, outLinkUid } = await authChatCert({ req, authToken: true });
const { file, bucketName, metadata } = await upload.doUpload(req, res);
await authUploadLimit(outLinkUid || tmbId);
addLog.info(`Upload file success ${file.originalname}, cost ${Date.now() - start}ms`);
......@@ -51,15 +50,19 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
metadata: metadata
});
return {
fileId,
previewUrl: `${ReadFileBaseUrl}?filename=${file.originalname}&token=${await createFileToken({
bucketName,
teamId,
tmbId,
fileId
})}`
};
jsonRes(res, {
data: {
fileId,
previewUrl: `${ReadFileBaseUrl}?filename=${file.originalname}&token=${await createFileToken(
{
bucketName,
teamId,
tmbId,
fileId
}
)}`
}
});
} catch (error) {
jsonRes(res, {
code: 500,
......
......@@ -35,6 +35,7 @@ import { AppContext } from '@/pages/app/detail/components/context';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
import VariableTip from '@/components/common/Textarea/MyTextarea/VariableTip';
import { getWebLLMModel } from '@/web/common/system/utils';
const DatasetSelectModal = dynamic(() => import('@/components/core/app/DatasetSelectModal'));
const DatasetParamsModal = dynamic(() => import('@/components/core/app/DatasetParamsModal'));
......@@ -121,8 +122,7 @@ const EditForm = ({
[appForm.chatConfig.variables, t]
);
const selectedModel =
llmModelList.find((item) => item.model === appForm.aiSettings.model) ?? llmModelList[0];
const selectedModel = getWebLLMModel(appForm.aiSettings.model);
const tokenLimit = useMemo(() => {
return selectedModel?.quoteMaxToken || 3000;
}, [selectedModel.quoteMaxToken]);
......
......@@ -29,6 +29,7 @@ import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
import ValueTypeLabel from './render/ValueTypeLabel';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { isWorkflowStartOutput } from '@fastgpt/global/core/workflow/template/system/workflowStart';
import { getWebLLMModel } from '@/web/common/system/utils';
const NodeDatasetConcat = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
const { t } = useTranslation();
......@@ -46,8 +47,7 @@ const NodeDatasetConcat = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
if (item.flowNodeType === FlowNodeTypeEnum.chatNode) {
const model =
item.inputs.find((item) => item.key === NodeInputKeyEnum.aiModel)?.value || '';
const quoteMaxToken =
llmModelList.find((item) => item.model === model)?.quoteMaxToken || 3000;
const quoteMaxToken = getWebLLMModel(model)?.quoteMaxToken || 3000;
maxTokens = Math.max(maxTokens, quoteMaxToken);
}
......
......@@ -11,6 +11,7 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
import SearchParamsTip from '@/components/core/dataset/SearchParamsTip';
import { useContextSelector } from 'use-context-selector';
import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context';
import { getWebLLMModel } from '@/web/common/system/utils';
const SelectDatasetParam = ({ inputs = [], nodeId }: RenderInputProps) => {
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
......@@ -36,8 +37,7 @@ const SelectDatasetParam = ({ inputs = [], nodeId }: RenderInputProps) => {
if (item.flowNodeType === FlowNodeTypeEnum.chatNode) {
const model =
item.inputs.find((item) => item.key === NodeInputKeyEnum.aiModel)?.value || '';
const quoteMaxToken =
llmModelList.find((item) => item.model === model)?.quoteMaxToken || 3000;
const quoteMaxToken = getWebLLMModel(model)?.quoteMaxToken || 3000;
maxTokens = Math.max(maxTokens, quoteMaxToken);
}
......
......@@ -338,7 +338,7 @@ export async function getServerSideProps(context: any) {
props: {
appId: context?.query?.appId || '',
chatId: context?.query?.chatId || '',
...(await serviceSideProps(context, ['file', 'app', 'chat']))
...(await serviceSideProps(context, ['file', 'app', 'chat', 'workflow']))
}
};
}
......
......@@ -394,7 +394,7 @@ export async function getServerSideProps(context: any) {
appIntro: app?.appId?.intro ?? 'intro',
shareId: shareId ?? '',
authToken: authToken ?? '',
...(await serviceSideProps(context, ['file', 'app', 'chat']))
...(await serviceSideProps(context, ['file', 'app', 'chat', 'workflow']))
}
};
}
......@@ -337,7 +337,7 @@ export async function getServerSideProps(context: any) {
chatId: context?.query?.chatId || '',
teamId: context?.query?.teamId || '',
teamToken: context?.query?.teamToken || '',
...(await serviceSideProps(context, ['file', 'app', 'chat']))
...(await serviceSideProps(context, ['file', 'app', 'chat', 'workflow']))
}
};
}
......
......@@ -103,7 +103,15 @@ export async function authChatCrud({
3. share page (body: shareId outLinkUid)
4. team chat page (body: teamId teamToken)
*/
export async function authChatCert(props: AuthModeType) {
export async function authChatCert(props: AuthModeType): Promise<{
teamId: string;
tmbId: string;
authType: AuthUserTypeEnum;
apikey: string;
isOwner: boolean;
canWrite: boolean;
outLinkUid?: string;
}> {
const { teamId, teamToken, shareId, outLinkUid } = props.req.body as OutLinkChatAuthProps;
if (shareId && outLinkUid) {
......
......@@ -3,6 +3,7 @@ import { UploadImgProps } from '@fastgpt/global/common/file/api';
import { BucketNameEnum } from '@fastgpt/global/common/file/constants';
import { preUploadImgProps } from '@fastgpt/global/common/file/api';
import { compressBase64Img, type CompressImgProps } from '@fastgpt/web/common/file/img';
import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat';
/**
* upload file to mongo gridfs
......@@ -10,11 +11,13 @@ import { compressBase64Img, type CompressImgProps } from '@fastgpt/web/common/fi
export const uploadFile2DB = ({
file,
bucketName,
outLinkAuthData,
metadata = {},
percentListen
}: {
file: File;
bucketName: `${BucketNameEnum}`;
outLinkAuthData?: OutLinkChatAuthProps;
metadata?: Record<string, any>;
percentListen?: (percent: number) => void;
}) => {
......@@ -22,6 +25,14 @@ export const uploadFile2DB = ({
form.append('metadata', JSON.stringify(metadata));
form.append('bucketName', bucketName);
form.append('file', file, encodeURIComponent(file.name));
if (outLinkAuthData) {
for (const key in outLinkAuthData) {
// @ts-ignore
outLinkAuthData[key] && form.append(key, outLinkAuthData[key]);
}
}
return postUploadFiles(form, (e) => {
if (!e.total) return;
......
import { useSystemStore } from './useSystemStore';
export const downloadFetch = async ({ url, filename }: { url: string; filename: string }) => {
const a = document.createElement('a');
a.href = url;
......@@ -6,3 +8,8 @@ export const downloadFetch = async ({ url, filename }: { url: string; filename:
a.click();
document.body.removeChild(a);
};
export const getWebLLMModel = (model?: string) => {
const list = useSystemStore.getState().llmModelList;
return list.find((item) => item.model === model || item.name === model) ?? list[0];
};
......@@ -1012,6 +1012,110 @@ export const simpleBotTemplates: TemplateType = [
export const workflowTemplates: TemplateType = [
{
id: 'workflow-default',
avatar: 'core/app/type/workflowFill',
name: '空白工作流',
intro: '从零开始构建工作流',
type: AppTypeEnum.workflow,
modules: [
{
nodeId: 'userGuide',
name: '系统配置',
intro: '可以配置应用的系统参数',
avatar: 'core/workflow/template/systemConfig',
flowNodeType: 'userGuide',
position: {
x: 262.2732338817093,
y: -476.00241136598146
},
version: '481',
inputs: [
{
key: 'welcomeText',
renderTypeList: ['hidden'],
valueType: 'string',
label: 'core.app.Welcome Text',
value: ''
},
{
key: 'variables',
renderTypeList: ['hidden'],
valueType: 'any',
label: 'core.app.Chat Variable',
value: []
},
{
key: 'questionGuide',
valueType: 'boolean',
renderTypeList: ['hidden'],
label: 'core.app.Question Guide',
value: false
},
{
key: 'tts',
renderTypeList: ['hidden'],
valueType: 'any',
label: '',
value: {
type: 'web'
}
},
{
key: 'whisper',
renderTypeList: ['hidden'],
valueType: 'any',
label: '',
value: {
open: false,
autoSend: false,
autoTTSResponse: false
}
},
{
key: 'scheduleTrigger',
renderTypeList: ['hidden'],
valueType: 'any',
label: '',
value: null
}
],
outputs: []
},
{
nodeId: '448745',
name: '流程开始',
intro: '',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: 'workflowStart',
position: {
x: 632.368838596004,
y: -347.7446492944009
},
version: '481',
inputs: [
{
key: 'userChatInput',
renderTypeList: ['reference', 'textarea'],
valueType: 'string',
label: '用户问题',
required: true,
toolDescription: '用户问题'
}
],
outputs: [
{
id: 'userChatInput',
key: 'userChatInput',
label: 'common:core.module.input.label.user question',
type: 'static',
valueType: 'string'
}
]
}
],
edges: []
},
{
id: 'TranslateRobot',
avatar: '/imgs/app/templates/translate.svg',
name: '多轮翻译机器人',
......@@ -2023,10 +2127,10 @@ export const workflowTemplates: TemplateType = [
]
},
{
id: 'dalle',
avatar: '/imgs/app/templates/dalle.svg',
name: 'Dalle3绘图',
intro: '通过请求Dalle3接口绘图,需要有 api key',
id: 'CQ',
avatar: 'core/workflow/template/questionClassify',
name: '问题分类 + 知识库',
intro: '先对用户的问题进行分类,再根据不同类型问题,执行不同的操作',
type: AppTypeEnum.workflow,
modules: [
{
......@@ -2034,7 +2138,7 @@ export const workflowTemplates: TemplateType = [
name: '系统配置',
intro: '可以配置应用的系统参数',
avatar: 'core/workflow/template/systemConfig',
flowNodeType: 'userGuide',
flowNodeType: FlowNodeTypeEnum.systemConfig,
position: {
x: 531.2422736065552,
y: -486.7611729549753
......@@ -2043,29 +2147,29 @@ export const workflowTemplates: TemplateType = [
inputs: [
{
key: 'welcomeText',
renderTypeList: ['hidden'],
valueType: 'string',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.string,
label: 'core.app.Welcome Text',
value: ''
value: '你好,我是知识库助手,请不要忘记选择知识库噢~\n[你是谁]\n[如何使用]'
},
{
key: 'variables',
renderTypeList: ['hidden'],
valueType: 'any',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: 'core.app.Chat Variable',
value: []
},
{
key: 'questionGuide',
valueType: 'boolean',
renderTypeList: ['hidden'],
valueType: WorkflowIOValueTypeEnum.boolean,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: 'core.app.Question Guide',
value: false
value: true
},
{
key: 'tts',
renderTypeList: ['hidden'],
valueType: 'any',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
value: {
type: 'web'
......@@ -2073,8 +2177,8 @@ export const workflowTemplates: TemplateType = [
},
{
key: 'whisper',
renderTypeList: ['hidden'],
valueType: 'any',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
value: {
open: false,
......@@ -2084,8 +2188,8 @@ export const workflowTemplates: TemplateType = [
},
{
key: 'scheduleTrigger',
renderTypeList: ['hidden'],
valueType: 'any',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
value: null
}
......@@ -2093,21 +2197,21 @@ export const workflowTemplates: TemplateType = [
outputs: []
},
{
nodeId: '448745',
nodeId: 'workflowStartNodeId',
name: '流程开始',
intro: '',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: 'workflowStart',
flowNodeType: FlowNodeTypeEnum.workflowStart,
position: {
x: 532.1275542407774,
y: 46.03775600322817
x: 558.4082376415505,
y: 123.72387429194112
},
version: '481',
inputs: [
{
key: 'userChatInput',
renderTypeList: ['reference', 'textarea'],
valueType: 'string',
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.textarea],
valueType: WorkflowIOValueTypeEnum.string,
label: '用户问题',
required: true,
toolDescription: '用户问题'
......@@ -2118,882 +2222,944 @@ export const workflowTemplates: TemplateType = [
id: 'userChatInput',
key: 'userChatInput',
label: 'core.module.input.label.user question',
type: 'static',
valueType: 'string'
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
]
},
{
nodeId: 'tMyUnRL5jIrC',
name: 'HTTP 请求',
intro: '可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
avatar: 'core/workflow/template/httpRequest',
flowNodeType: 'httpRequest468',
nodeId: '7BdojPlukIQw',
name: 'AI 对话',
intro: 'AI 大模型对话',
avatar: 'core/workflow/template/aiChat',
flowNodeType: FlowNodeTypeEnum.chatNode,
showStatus: true,
position: {
x: 931.6784209157559,
y: -162.36850541742047
x: 2701.1267277679685,
y: -767.8956312653042
},
version: '486',
version: '481',
inputs: [
{
key: 'system_addInputParam',
renderTypeList: ['addInputParam'],
valueType: 'dynamic',
label: '',
required: false,
description: 'core.module.input.description.HTTP Dynamic Input',
editField: {
key: true,
valueType: true
},
customInputConfig: {
selectValueTypeList: [
'string',
'number',
'boolean',
'object',
'arrayString',
'arrayNumber',
'arrayBoolean',
'arrayObject',
'any',
'chatHistory',
'datasetQuote',
'dynamic',
'selectApp',
'selectDataset'
],
showDescription: false,
showDefaultValue: true
}
key: 'model',
renderTypeList: [
FlowNodeInputTypeEnum.settingLLMModel,
FlowNodeInputTypeEnum.reference
],
label: 'core.module.input.label.aiModel',
valueType: WorkflowIOValueTypeEnum.string,
value: 'gpt-4o-mini'
},
{
key: 'system_httpMethod',
renderTypeList: ['custom'],
valueType: 'string',
key: 'temperature',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
value: 'POST',
required: true
value: 3,
valueType: WorkflowIOValueTypeEnum.number,
min: 0,
max: 10,
step: 1
},
{
key: 'system_httpReqUrl',
renderTypeList: ['hidden'],
valueType: 'string',
key: 'maxToken',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
description: 'core.module.input.description.Http Request Url',
placeholder: 'https://api.ai.com/getInventory',
required: false,
value: 'https://api.openai.com/v1/images/generations'
value: 1950,
valueType: WorkflowIOValueTypeEnum.number,
min: 100,
max: 4000,
step: 50
},
{
key: 'system_httpHeader',
renderTypeList: ['custom'],
valueType: 'any',
value: [
{
key: 'Authorization',
type: 'string',
value: 'Bearer '
}
],
key: 'isResponseAnswerText',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
description: 'core.module.input.description.Http Request Header',
placeholder: 'core.module.input.description.Http Request Header',
required: false
value: true,
valueType: WorkflowIOValueTypeEnum.boolean
},
{
key: 'system_httpParams',
renderTypeList: ['hidden'],
valueType: 'any',
value: [],
key: 'quoteTemplate',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
required: false
valueType: WorkflowIOValueTypeEnum.string
},
{
key: 'system_httpJsonBody',
renderTypeList: ['hidden'],
valueType: 'any',
value:
'{\n "model": "dall-e-3",\n "prompt": "{{prompt}}",\n "n": 1,\n "size": "1024x1024"\n}',
key: 'quotePrompt',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
required: false
valueType: WorkflowIOValueTypeEnum.string
},
{
key: 'prompt',
valueType: 'string',
label: 'prompt',
renderTypeList: ['reference'],
key: 'systemPrompt',
renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference],
max: 3000,
valueType: WorkflowIOValueTypeEnum.string,
label: 'core.ai.Prompt',
description: 'core.app.tip.chatNodeSystemPromptTip',
placeholder: 'core.app.tip.chatNodeSystemPromptTip',
value: ''
},
{
key: 'history',
renderTypeList: [FlowNodeInputTypeEnum.numberInput, FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.chatHistory,
label: 'core.module.input.label.chat history',
required: true,
min: 0,
max: 30,
value: 6
},
{
key: 'userChatInput',
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.textarea],
valueType: WorkflowIOValueTypeEnum.string,
label: '用户问题',
required: true,
toolDescription: '用户问题',
value: ['workflowStartNodeId', 'userChatInput']
},
{
key: 'quoteQA',
renderTypeList: [FlowNodeInputTypeEnum.settingDatasetQuotePrompt],
label: '',
debugLabel: '知识库引用',
description: '',
canEdit: true,
editField: {
key: true,
valueType: true
},
value: ['448745', 'userChatInput']
valueType: WorkflowIOValueTypeEnum.datasetQuote,
value: ['MNMMMIjjWyMU', 'quoteQA']
}
],
outputs: [
{
id: 'system_addOutputParam',
key: 'system_addOutputParam',
type: 'dynamic',
valueType: 'dynamic',
label: '',
customFieldConfig: {
selectValueTypeList: [
'string',
'number',
'boolean',
'object',
'arrayString',
'arrayNumber',
'arrayBoolean',
'arrayObject',
'any',
'chatHistory',
'datasetQuote',
'dynamic',
'selectApp',
'selectDataset'
],
showDescription: false,
showDefaultValue: true
}
id: 'history',
key: 'history',
label: 'core.module.output.label.New context',
description: 'core.module.output.description.New context',
valueType: WorkflowIOValueTypeEnum.chatHistory,
type: FlowNodeOutputTypeEnum.static
},
{
id: 'error',
key: 'error',
label: '请求错误',
description: 'HTTP请求错误信息,成功时返回空',
valueType: 'object',
type: 'static'
id: 'answerText',
key: 'answerText',
label: 'core.module.output.label.Ai response content',
description: 'core.module.output.description.Ai response content',
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
]
},
{
nodeId: 'rvbo634w3AYj',
name: '问题分类',
intro:
'根据用户的历史记录和当前问题判断该次提问的类型。可以添加多组问题类型,下面是一个模板例子:\n类型1: 打招呼\n类型2: 关于商品“使用”问题\n类型3: 关于商品“购买”问题\n类型4: 其他问题',
avatar: 'core/workflow/template/questionClassify',
flowNodeType: FlowNodeTypeEnum.classifyQuestion,
showStatus: true,
position: {
x: 1020.9667229609946,
y: -385.0060974413916
},
version: '481',
inputs: [
{
key: 'model',
renderTypeList: [FlowNodeInputTypeEnum.selectLLMModel, FlowNodeInputTypeEnum.reference],
label: 'core.module.input.label.aiModel',
required: true,
valueType: WorkflowIOValueTypeEnum.string,
llmModelType: 'classify',
value: 'gpt-4o-mini'
},
{
id: 'httpRawResponse',
key: 'httpRawResponse',
label: '原始响应',
key: 'systemPrompt',
renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference],
max: 3000,
valueType: WorkflowIOValueTypeEnum.string,
label: 'core.module.input.label.Background',
description: 'core.module.input.description.Background',
placeholder: 'core.module.input.placeholder.Classify background',
value: ''
},
{
key: 'history',
renderTypeList: [FlowNodeInputTypeEnum.numberInput, FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.chatHistory,
label: 'core.module.input.label.chat history',
required: true,
description: 'HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。',
valueType: 'any',
type: 'static'
min: 0,
max: 30,
value: 6
},
{
id: 'DeKGGioBwaMf',
type: 'dynamic',
key: 'data[0].url',
valueType: 'string',
label: 'data[0].url'
key: 'userChatInput',
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.textarea],
valueType: WorkflowIOValueTypeEnum.string,
label: '用户问题',
required: true,
value: ['workflowStartNodeId', 'userChatInput']
},
{
key: 'agents',
renderTypeList: [FlowNodeInputTypeEnum.custom],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
value: [
{
value: '关于电影《星际穿越》的问题',
key: 'wqre'
},
{
value: '打招呼、问候等问题',
key: 'sdfa'
},
{
value: '其他问题',
key: 'agex'
}
]
}
],
outputs: [
{
id: 'cqResult',
key: 'cqResult',
label: '分类结果',
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
]
},
{
nodeId: '7mapnCgHfKW6',
nodeId: '7kwgL1dVlwG6',
name: '指定回复',
intro:
'该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。',
avatar: 'core/workflow/template/reply',
flowNodeType: 'answerNode',
flowNodeType: FlowNodeTypeEnum.answerNode,
position: {
x: 2204.4609372615846,
y: 163.11883652393863
x: 1874.9167551056487,
y: 434.98431875888207
},
version: '481',
inputs: [
{
key: 'text',
renderTypeList: ['textarea', 'reference'],
valueType: 'any',
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',
selectedTypeIndex: 1,
value: ['vEXJF8pQ8eOv', 'system_text'],
required: true
value: ['rvbo634w3AYj', 'cqResult']
}
],
outputs: []
},
{
nodeId: 'vEXJF8pQ8eOv',
name: '文本拼接',
intro: '可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。',
avatar: 'core/workflow/template/textConcat',
flowNodeType: 'textEditor',
nodeId: 'MNMMMIjjWyMU',
name: '知识库搜索',
intro: '调用“语义检索”和“全文检索”能力,从“知识库”中查找可能与问题相关的参考内容',
avatar: 'core/workflow/template/datasetSearch',
flowNodeType: FlowNodeTypeEnum.datasetSearchNode,
showStatus: true,
position: {
x: 1544.8821308368042,
y: -27.22950739442814
x: 1851.010152279949,
y: -613.3555232387284
},
version: '486',
version: '481',
inputs: [
{
key: 'system_addInputParam',
renderTypeList: ['addInputParam'],
valueType: 'dynamic',
key: 'datasets',
renderTypeList: [FlowNodeInputTypeEnum.selectDataset, FlowNodeInputTypeEnum.reference],
label: 'core.module.input.label.Select dataset',
value: [],
valueType: WorkflowIOValueTypeEnum.selectDataset,
list: [],
required: true
},
{
key: 'similarity',
renderTypeList: [FlowNodeInputTypeEnum.selectDatasetParamsModal],
label: '',
required: false,
description: '可以引用其他节点的输出,作为文本拼接的变量,通过 {{字段名}} 来引用变量',
customInputConfig: {
selectValueTypeList: [
'string',
'number',
'boolean',
'object',
'arrayString',
'arrayNumber',
'arrayBoolean',
'arrayObject',
'any',
'chatHistory',
'datasetQuote',
'dynamic',
'selectApp',
'selectDataset'
],
showDescription: false,
showDefaultValue: false
}
value: 0.4,
valueType: WorkflowIOValueTypeEnum.number
},
{
key: 'system_textareaInput',
renderTypeList: ['textarea'],
valueType: 'string',
required: true,
label: '拼接文本',
placeholder: '可通过 {{字段名}} 来引用变量',
value: '![]({{url}})'
key: 'limit',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
value: 1500,
valueType: WorkflowIOValueTypeEnum.number
},
{
renderTypeList: ['reference'],
valueType: 'string',
canEdit: true,
key: 'url',
label: 'url',
customInputConfig: {
selectValueTypeList: [
'string',
'number',
'boolean',
'object',
'arrayString',
'arrayNumber',
'arrayBoolean',
'arrayObject',
'any',
'chatHistory',
'datasetQuote',
'dynamic',
'selectApp',
'selectDataset'
],
showDescription: false,
showDefaultValue: false
},
key: 'searchMode',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string,
value: 'embedding'
},
{
key: 'usingReRank',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.boolean,
value: false
},
{
key: 'datasetSearchUsingExtensionQuery',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.boolean,
value: true
},
{
key: 'datasetSearchExtensionModel',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
},
{
key: 'datasetSearchExtensionBg',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string,
value: ''
},
{
key: 'userChatInput',
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.textarea],
valueType: WorkflowIOValueTypeEnum.string,
label: '用户问题',
required: true,
value: ['tMyUnRL5jIrC', 'DeKGGioBwaMf']
toolDescription: '需要检索的内容',
value: ['workflowStartNodeId', 'userChatInput']
}
],
outputs: [
{
id: 'system_text',
key: 'system_text',
label: '拼接结果',
type: 'static',
valueType: 'string'
id: 'quoteQA',
key: 'quoteQA',
label: 'core.module.Dataset quote.label',
description: '特殊数组格式,搜索结果为空时,返回空数组。',
type: FlowNodeOutputTypeEnum.static,
valueType: WorkflowIOValueTypeEnum.datasetQuote
}
]
}
],
edges: [
{
source: '448745',
target: 'tMyUnRL5jIrC',
sourceHandle: '448745-source-right',
targetHandle: 'tMyUnRL5jIrC-target-left'
source: 'workflowStartNodeId',
target: 'rvbo634w3AYj',
sourceHandle: 'workflowStartNodeId-source-right',
targetHandle: 'rvbo634w3AYj-target-left'
},
{
source: 'rvbo634w3AYj',
target: '7kwgL1dVlwG6',
sourceHandle: 'rvbo634w3AYj-source-agex',
targetHandle: '7kwgL1dVlwG6-target-left'
},
{
source: 'rvbo634w3AYj',
target: 'MNMMMIjjWyMU',
sourceHandle: 'rvbo634w3AYj-source-wqre',
targetHandle: 'MNMMMIjjWyMU-target-left'
},
{
source: 'tMyUnRL5jIrC',
target: 'vEXJF8pQ8eOv',
sourceHandle: 'tMyUnRL5jIrC-source-right',
targetHandle: 'vEXJF8pQ8eOv-target-left'
source: 'MNMMMIjjWyMU',
target: '7BdojPlukIQw',
sourceHandle: 'MNMMMIjjWyMU-source-right',
targetHandle: '7BdojPlukIQw-target-left'
},
{
source: 'vEXJF8pQ8eOv',
target: '7mapnCgHfKW6',
sourceHandle: 'vEXJF8pQ8eOv-source-right',
targetHandle: '7mapnCgHfKW6-target-left'
source: 'rvbo634w3AYj',
target: '7kwgL1dVlwG6',
sourceHandle: 'rvbo634w3AYj-source-sdfa',
targetHandle: '7kwgL1dVlwG6-target-left'
}
]
},
}
];
export const pluginTemplates: TemplateType = [
{
id: 'CQ',
avatar: 'core/workflow/template/questionClassify',
name: '问题分类 + 知识库',
intro: '先对用户的问题进行分类,再根据不同类型问题,执行不同的操作',
type: AppTypeEnum.workflow,
id: 'plugin-simple',
avatar: 'core/workflow/template/aiChat',
name: '默认模板',
intro: '标准的插件初始模板',
type: AppTypeEnum.plugin,
modules: [
{
nodeId: 'userGuide',
name: '系统配置',
intro: '可以配置应用的系统参数',
avatar: 'core/workflow/template/systemConfig',
flowNodeType: FlowNodeTypeEnum.systemConfig,
nodeId: 'pluginInput',
name: '自定义插件输入',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: FlowNodeTypeEnum.pluginInput,
showStatus: false,
position: {
x: 531.2422736065552,
y: -486.7611729549753
x: 616.4226348688949,
y: -165.05298493910115
},
version: '481',
inputs: [
{
key: 'welcomeText',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.string,
label: 'core.app.Welcome Text',
value: '你好,我是知识库助手,请不要忘记选择知识库噢~\n[你是谁]\n[如何使用]'
},
{
key: 'variables',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: 'core.app.Chat Variable',
value: []
},
{
key: 'questionGuide',
valueType: WorkflowIOValueTypeEnum.boolean,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: 'core.app.Question Guide',
value: true
},
{
key: 'tts',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
value: {
type: 'web'
}
},
{
key: 'whisper',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
value: {
open: false,
autoSend: false,
autoTTSResponse: false
}
},
{
key: 'scheduleTrigger',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
value: null
}
],
inputs: [],
outputs: []
},
{
nodeId: 'workflowStartNodeId',
name: '流程开始',
intro: '',
nodeId: 'pluginOutput',
name: '自定义插件输出',
avatar: '/imgs/workflow/output.png',
flowNodeType: FlowNodeTypeEnum.pluginOutput,
showStatus: false,
position: {
x: 1607.7142331269126,
y: -151.8669210746189
},
version: '481',
inputs: [],
outputs: []
}
],
edges: []
},
{
id: 'plugin-feishu',
avatar: '/imgs/app/templates/feishu.svg',
name: '飞书webhook插件',
intro: '通过 webhook 给飞书机器人发送一条消息',
type: AppTypeEnum.plugin,
modules: [
{
nodeId: 'pluginInput',
name: '自定义插件输入',
intro: '自定义配置外部输入,使用插件时,仅暴露自定义配置的输入',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: FlowNodeTypeEnum.workflowStart,
flowNodeType: 'pluginInput',
showStatus: false,
position: {
x: 558.4082376415505,
y: 123.72387429194112
x: 517.5620777851774,
y: -173.55711888178655
},
version: '481',
inputs: [
{
key: 'userChatInput',
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.textarea],
valueType: WorkflowIOValueTypeEnum.string,
label: '用户问题',
inputType: 'input',
valueType: 'string',
key: '飞书机器人地址',
label: '飞书机器人地址',
description: '',
isToolInput: false,
defaultValue: '',
editField: {
key: true
},
dynamicParamDefaultValue: {
inputType: 'reference',
valueType: 'string',
required: true
},
renderTypeList: ['input'],
required: true,
toolDescription: '用户问题'
canEdit: true,
value: ''
},
{
key: '发送的消息',
valueType: 'string',
label: '发送的消息',
renderTypeList: ['reference'],
required: true,
description: '',
canEdit: true,
value: '',
editField: {
key: true
},
dynamicParamDefaultValue: {
inputType: 'reference',
valueType: 'string',
required: true
}
}
],
outputs: [
{
id: 'userChatInput',
key: 'userChatInput',
label: 'core.module.input.label.user question',
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
id: 'mv52BrPVE6bm',
key: '飞书机器人地址',
valueType: 'string',
label: '飞书机器人地址',
type: 'static'
},
{
id: 'p0m68Dv5KaIp',
key: '发送的消息',
valueType: 'string',
label: '发送的消息',
type: 'static'
}
]
},
{
nodeId: '7BdojPlukIQw',
name: 'AI 对话',
intro: 'AI 大模型对话',
avatar: 'core/workflow/template/aiChat',
flowNodeType: FlowNodeTypeEnum.chatNode,
showStatus: true,
nodeId: 'pluginOutput',
name: '自定义插件输出',
intro: '自定义配置外部输出,使用插件时,仅暴露自定义配置的输出',
avatar: '/imgs/workflow/output.png',
flowNodeType: 'pluginOutput',
showStatus: false,
position: {
x: 2701.1267277679685,
y: -767.8956312653042
x: 1668.9410524554828,
y: -153.47815316221283
},
version: '481',
inputs: [
{
key: 'model',
renderTypeList: [
FlowNodeInputTypeEnum.settingLLMModel,
FlowNodeInputTypeEnum.reference
],
label: 'core.module.input.label.aiModel',
valueType: WorkflowIOValueTypeEnum.string,
value: 'gpt-4o-mini'
},
{
key: 'temperature',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
value: 3,
valueType: WorkflowIOValueTypeEnum.number,
min: 0,
max: 10,
step: 1
},
inputs: [],
outputs: []
},
{
nodeId: 'rKBYGQuYefae',
name: 'HTTP 请求',
intro: '可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
avatar: 'core/workflow/template/httpRequest',
flowNodeType: 'httpRequest468',
showStatus: true,
position: {
x: 1069.7228495148624,
y: -392.26482361861054
},
version: '481',
inputs: [
{
key: 'maxToken',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
key: 'system_addInputParam',
renderTypeList: ['addInputParam'],
valueType: 'dynamic',
label: '',
value: 1950,
valueType: WorkflowIOValueTypeEnum.number,
min: 100,
max: 4000,
step: 50
required: false,
description: 'core.module.input.description.HTTP Dynamic Input'
},
{
key: 'isResponseAnswerText',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
value: true,
valueType: WorkflowIOValueTypeEnum.boolean
key: 'text',
valueType: 'string',
label: 'text',
renderTypeList: ['reference'],
description: '',
canEdit: true,
editField: {
key: true,
valueType: true
},
value: ['pluginInput', 'p0m68Dv5KaIp']
},
{
key: 'quoteTemplate',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
key: 'url',
valueType: 'string',
label: 'url',
renderTypeList: ['reference'],
description: '',
canEdit: true,
editField: {
key: true,
valueType: true
},
value: ['pluginInput', 'mv52BrPVE6bm']
},
{
key: 'quotePrompt',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
key: 'system_httpMethod',
renderTypeList: ['custom'],
valueType: 'string',
label: '',
valueType: WorkflowIOValueTypeEnum.string
value: 'POST',
required: true
},
{
key: 'systemPrompt',
renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference],
max: 3000,
valueType: WorkflowIOValueTypeEnum.string,
label: 'core.ai.Prompt',
description: 'core.app.tip.chatNodeSystemPromptTip',
placeholder: 'core.app.tip.chatNodeSystemPromptTip',
value: ''
key: 'system_httpReqUrl',
renderTypeList: ['hidden'],
valueType: 'string',
label: '',
description: 'core.module.input.description.Http Request Url',
placeholder: 'https://api.ai.com/getInventory',
required: false,
value: '{{url}}'
},
{
key: 'history',
renderTypeList: [FlowNodeInputTypeEnum.numberInput, FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.chatHistory,
label: 'core.module.input.label.chat history',
required: true,
min: 0,
max: 30,
value: 6
key: 'system_httpHeader',
renderTypeList: ['custom'],
valueType: 'any',
value: [],
label: '',
description: 'core.module.input.description.Http Request Header',
placeholder: 'core.module.input.description.Http Request Header',
required: false
},
{
key: 'userChatInput',
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.textarea],
valueType: WorkflowIOValueTypeEnum.string,
label: '用户问题',
required: true,
toolDescription: '用户问题',
value: ['workflowStartNodeId', 'userChatInput']
key: 'system_httpParams',
renderTypeList: ['hidden'],
valueType: 'any',
value: [],
label: '',
required: false
},
{
key: 'quoteQA',
renderTypeList: [FlowNodeInputTypeEnum.settingDatasetQuotePrompt],
key: 'system_httpJsonBody',
renderTypeList: ['hidden'],
valueType: 'any',
value:
'{\r\n "msg_type": "text",\r\n "content": {\r\n "text": "{{text}}"\r\n }\r\n}',
label: '',
debugLabel: '知识库引用',
description: '',
valueType: WorkflowIOValueTypeEnum.datasetQuote,
value: ['MNMMMIjjWyMU', 'quoteQA']
required: false
}
],
outputs: [
{
id: 'history',
key: 'history',
label: 'core.module.output.label.New context',
description: 'core.module.output.description.New context',
valueType: WorkflowIOValueTypeEnum.chatHistory,
type: FlowNodeOutputTypeEnum.static
id: 'system_addOutputParam',
key: 'system_addOutputParam',
type: 'dynamic',
valueType: 'dynamic',
label: '',
editField: {
key: true,
valueType: true
}
},
{
id: 'answerText',
key: 'answerText',
label: 'core.module.output.label.Ai response content',
description: 'core.module.output.description.Ai response content',
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
id: 'error',
key: 'error',
label: '请求错误',
description: 'HTTP请求错误信息,成功时返回空',
valueType: 'object',
type: 'static'
},
{
id: 'httpRawResponse',
key: 'httpRawResponse',
label: '原始响应',
required: true,
description: 'HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。',
valueType: 'any',
type: 'static'
}
]
}
],
edges: [
{
source: 'pluginInput',
target: 'rKBYGQuYefae',
sourceHandle: 'pluginInput-source-right',
targetHandle: 'rKBYGQuYefae-target-left'
},
{
nodeId: 'rvbo634w3AYj',
name: '问题分类',
intro:
'根据用户的历史记录和当前问题判断该次提问的类型。可以添加多组问题类型,下面是一个模板例子:\n类型1: 打招呼\n类型2: 关于商品“使用”问题\n类型3: 关于商品“购买”问题\n类型4: 其他问题',
avatar: 'core/workflow/template/questionClassify',
flowNodeType: FlowNodeTypeEnum.classifyQuestion,
showStatus: true,
source: 'rKBYGQuYefae',
target: 'pluginOutput',
sourceHandle: 'rKBYGQuYefae-source-right',
targetHandle: 'pluginOutput-target-left'
}
]
},
{
id: 'dalle',
avatar: '/imgs/model/openai.svg',
name: 'Dalle3绘图',
intro: '通过请求Dalle3接口绘图,需要有 api key',
type: AppTypeEnum.plugin,
modules: [
{
nodeId: 'pluginInput',
name: '自定义插件输入',
intro: '可以配置插件需要哪些输入,利用这些输入来运行插件',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: 'pluginInput',
showStatus: false,
position: {
x: 1020.9667229609946,
y: -385.0060974413916
x: 412.7756423516722,
y: -99.80686112290361
},
version: '481',
inputs: [
{
key: 'model',
renderTypeList: [FlowNodeInputTypeEnum.selectLLMModel, FlowNodeInputTypeEnum.reference],
label: 'core.module.input.label.aiModel',
required: true,
valueType: WorkflowIOValueTypeEnum.string,
llmModelType: 'classify',
value: 'gpt-4o-mini'
},
{
key: 'systemPrompt',
renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference],
max: 3000,
valueType: WorkflowIOValueTypeEnum.string,
label: 'core.module.input.label.Background',
description: 'core.module.input.description.Background',
placeholder: 'core.module.input.placeholder.Classify background',
value: ''
},
{
key: 'history',
renderTypeList: [FlowNodeInputTypeEnum.numberInput, FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.chatHistory,
label: 'core.module.input.label.chat history',
required: true,
min: 0,
max: 30,
value: 6
},
{
key: 'userChatInput',
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.textarea],
valueType: WorkflowIOValueTypeEnum.string,
label: '用户问题',
renderTypeList: ['reference'],
selectedTypeIndex: 0,
valueType: 'string',
canEdit: true,
key: '绘图提示词',
label: '绘图提示词',
description: '绘图提示词',
required: true,
value: ['workflowStartNodeId', 'userChatInput']
},
{
key: 'agents',
renderTypeList: [FlowNodeInputTypeEnum.custom],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
value: [
{
value: '关于电影《星际穿越》的问题',
key: 'wqre'
},
{
value: '打招呼、问候等问题',
key: 'sdfa'
},
{
value: '其他问题',
key: 'agex'
}
]
toolDescription: '绘图提示词'
}
],
outputs: [
{
id: 'cqResult',
key: 'cqResult',
label: '分类结果',
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
]
},
{
nodeId: '7kwgL1dVlwG6',
name: '指定回复',
intro:
'该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。',
avatar: 'core/workflow/template/reply',
flowNodeType: FlowNodeTypeEnum.answerNode,
id: '绘图提示词',
valueType: 'string',
key: '绘图提示词',
label: '绘图提示词',
type: 'hidden'
}
]
},
{
nodeId: 'pluginOutput',
name: '自定义插件输出',
intro: '自定义配置外部输出,使用插件时,仅暴露自定义配置的输出',
avatar: 'core/workflow/template/pluginOutput',
flowNodeType: 'pluginOutput',
showStatus: false,
position: {
x: 1874.9167551056487,
y: 434.98431875888207
x: 1822.7195641525896,
y: -193.54601587659562
},
version: '481',
inputs: [
{
key: 'text',
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',
selectedTypeIndex: 1,
value: ['rvbo634w3AYj', 'cqResult']
renderTypeList: ['reference'],
valueType: 'string',
canEdit: true,
key: '图片访问链接',
label: '图片访问链接',
description: '',
value: ['tMvel910bnrJ', 'pJXgWoTpPoMy']
},
{
renderTypeList: ['reference'],
valueType: 'object',
canEdit: true,
key: 'error',
label: '错误信息',
description: '',
value: ['tMvel910bnrJ', 'error']
}
],
outputs: []
},
{
nodeId: 'MNMMMIjjWyMU',
name: '知识库搜索',
intro: '调用“语义检索”和“全文检索”能力,从“知识库”中查找可能与问题相关的参考内容',
avatar: 'core/workflow/template/datasetSearch',
flowNodeType: FlowNodeTypeEnum.datasetSearchNode,
nodeId: 'tMvel910bnrJ',
name: 'HTTP 请求',
intro: '可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
avatar: 'core/workflow/template/httpRequest',
flowNodeType: 'httpRequest468',
showStatus: true,
position: {
x: 1851.010152279949,
y: -613.3555232387284
x: 1044.8838211811253,
y: -414.7785530936485
},
version: '481',
inputs: [
{
key: 'datasets',
renderTypeList: [FlowNodeInputTypeEnum.selectDataset, FlowNodeInputTypeEnum.reference],
label: 'core.module.input.label.Select dataset',
value: [],
valueType: WorkflowIOValueTypeEnum.selectDataset,
list: [],
required: true
},
{
key: 'similarity',
renderTypeList: [FlowNodeInputTypeEnum.selectDatasetParamsModal],
label: '',
value: 0.4,
valueType: WorkflowIOValueTypeEnum.number
},
{
key: 'limit',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
key: 'system_addInputParam',
renderTypeList: ['addInputParam'],
valueType: 'dynamic',
label: '',
value: 1500,
valueType: WorkflowIOValueTypeEnum.number
required: false,
description: 'core.module.input.description.HTTP Dynamic Input',
customInputConfig: {
selectValueTypeList: [
'string',
'number',
'boolean',
'object',
'arrayString',
'arrayNumber',
'arrayBoolean',
'arrayObject',
'any',
'chatHistory',
'datasetQuote',
'dynamic',
'selectApp',
'selectDataset'
],
showDescription: false,
showDefaultValue: true
}
},
{
key: 'searchMode',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
key: 'system_httpMethod',
renderTypeList: ['custom'],
valueType: 'string',
label: '',
valueType: WorkflowIOValueTypeEnum.string,
value: 'embedding'
value: 'POST',
required: true
},
{
key: 'usingReRank',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
key: 'system_httpReqUrl',
renderTypeList: ['hidden'],
valueType: 'string',
label: '',
valueType: WorkflowIOValueTypeEnum.boolean,
value: false
description: 'core.module.input.description.Http Request Url',
placeholder: 'https://api.ai.com/getInventory',
required: false,
value: '{{url}}/v1/images/generations'
},
{
key: 'datasetSearchUsingExtensionQuery',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
key: 'system_httpHeader',
renderTypeList: ['custom'],
valueType: 'any',
value: [
{
key: 'Authorization',
type: 'string',
value: 'Bearer {{authorization}}'
}
],
label: '',
valueType: WorkflowIOValueTypeEnum.boolean,
value: true
description: 'core.module.input.description.Http Request Header',
placeholder: 'core.module.input.description.Http Request Header',
required: false
},
{
key: 'datasetSearchExtensionModel',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
key: 'system_httpParams',
renderTypeList: ['hidden'],
valueType: 'any',
value: [],
label: '',
valueType: WorkflowIOValueTypeEnum.string
required: false
},
{
key: 'datasetSearchExtensionBg',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
key: 'system_httpJsonBody',
renderTypeList: ['hidden'],
valueType: 'any',
value:
'{\n "model": "dall-e-3",\n "prompt": "{{prompt}}",\n "n": 1,\n "size": "1024x1024"\n}',
label: '',
valueType: WorkflowIOValueTypeEnum.string,
value: ''
required: false
},
{
key: 'userChatInput',
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.textarea],
valueType: WorkflowIOValueTypeEnum.string,
label: '用户问题',
renderTypeList: ['reference'],
valueType: 'string',
canEdit: true,
key: 'prompt',
label: 'prompt',
customInputConfig: {
selectValueTypeList: [
'string',
'number',
'boolean',
'object',
'arrayString',
'arrayNumber',
'arrayBoolean',
'arrayObject',
'any',
'chatHistory',
'datasetQuote',
'dynamic',
'selectApp',
'selectDataset'
],
showDescription: false,
showDefaultValue: true
},
required: true,
toolDescription: '需要检索的内容',
value: ['workflowStartNodeId', 'userChatInput']
value: ['pluginInput', '绘图提示词']
}
],
outputs: [
{
id: 'quoteQA',
key: 'quoteQA',
label: 'core.module.Dataset quote.label',
description: '特殊数组格式,搜索结果为空时,返回空数组。',
type: FlowNodeOutputTypeEnum.static,
valueType: WorkflowIOValueTypeEnum.datasetQuote
}
]
}
],
edges: [
{
source: 'workflowStartNodeId',
target: 'rvbo634w3AYj',
sourceHandle: 'workflowStartNodeId-source-right',
targetHandle: 'rvbo634w3AYj-target-left'
},
{
source: 'rvbo634w3AYj',
target: '7kwgL1dVlwG6',
sourceHandle: 'rvbo634w3AYj-source-agex',
targetHandle: '7kwgL1dVlwG6-target-left'
},
{
source: 'rvbo634w3AYj',
target: 'MNMMMIjjWyMU',
sourceHandle: 'rvbo634w3AYj-source-wqre',
targetHandle: 'MNMMMIjjWyMU-target-left'
},
{
source: 'MNMMMIjjWyMU',
target: '7BdojPlukIQw',
sourceHandle: 'MNMMMIjjWyMU-source-right',
targetHandle: '7BdojPlukIQw-target-left'
},
{
source: 'rvbo634w3AYj',
target: '7kwgL1dVlwG6',
sourceHandle: 'rvbo634w3AYj-source-sdfa',
targetHandle: '7kwgL1dVlwG6-target-left'
id: 'error',
key: 'error',
label: '请求错误',
description: 'HTTP请求错误信息,成功时返回空',
valueType: 'object',
type: 'static'
},
{
id: 'httpRawResponse',
key: 'httpRawResponse',
label: '原始响应',
required: true,
description: 'HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。',
valueType: 'any',
type: 'static'
},
{
id: 'system_addOutputParam',
key: 'system_addOutputParam',
type: 'dynamic',
valueType: 'dynamic',
label: '',
customFieldConfig: {
selectValueTypeList: [
'string',
'number',
'boolean',
'object',
'arrayString',
'arrayNumber',
'arrayBoolean',
'arrayObject',
'any',
'chatHistory',
'datasetQuote',
'dynamic',
'selectApp',
'selectDataset'
],
showDescription: false,
showDefaultValue: false
}
},
{
id: 'pJXgWoTpPoMy',
valueType: 'string',
type: 'dynamic',
key: 'data[0].url',
label: 'data[0].url'
}
]
}
]
}
];
export const pluginTemplates: TemplateType = [
{
id: 'plugin-simple',
avatar: 'core/workflow/template/aiChat',
name: '默认模板',
intro: '标准的插件初始模板',
type: AppTypeEnum.plugin,
modules: [
],
edges: [
{
nodeId: 'pluginInput',
name: '自定义插件输入',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: FlowNodeTypeEnum.pluginInput,
showStatus: false,
position: {
x: 616.4226348688949,
y: -165.05298493910115
},
version: '481',
inputs: [],
outputs: []
source: 'pluginInput',
target: 'tMvel910bnrJ',
sourceHandle: 'pluginInput-source-right',
targetHandle: 'tMvel910bnrJ-target-left'
},
{
nodeId: 'pluginOutput',
name: '自定义插件输出',
avatar: '/imgs/workflow/output.png',
flowNodeType: FlowNodeTypeEnum.pluginOutput,
showStatus: false,
position: {
x: 1607.7142331269126,
y: -151.8669210746189
},
version: '481',
inputs: [],
outputs: []
source: 'tMvel910bnrJ',
target: 'pluginOutput',
sourceHandle: 'tMvel910bnrJ-source-right',
targetHandle: 'pluginOutput-target-left'
}
],
edges: []
]
},
{
id: 'plugin-feishu',
avatar: '/imgs/app/templates/feishu.svg',
name: '飞书webhook插件',
intro: '通过 webhook 给飞书机器人发送一条消息',
id: 'flux',
avatar: '/imgs/app/templates/flux.svg',
name: 'Flux 绘图',
intro: '通过请求 Flux 接口绘图,需要有 api key',
type: AppTypeEnum.plugin,
modules: [
{
nodeId: 'pluginInput',
name: '自定义插件输入',
intro: '自定义配置外部输入,使用插件时,仅暴露自定义配置的输入',
intro: '可以配置插件需要哪些输入,利用这些输入来运行插件',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: 'pluginInput',
showStatus: false,
position: {
x: 517.5620777851774,
y: -173.55711888178655
x: 351.2046235980429,
y: -77.41739975794749
},
version: '481',
inputs: [
{
inputType: 'input',
renderTypeList: ['reference'],
selectedTypeIndex: 0,
valueType: 'string',
key: '飞书机器人地址',
label: '飞书机器人地址',
description: '',
isToolInput: false,
defaultValue: '',
editField: {
key: true
},
dynamicParamDefaultValue: {
inputType: 'reference',
valueType: 'string',
required: true
},
renderTypeList: ['input'],
required: true,
canEdit: true,
value: ''
},
{
key: '发送的消息',
valueType: 'string',
label: '发送的消息',
renderTypeList: ['reference'],
key: '绘图提示词',
label: '绘图提示词',
description: '绘图提示词',
required: true,
description: '',
canEdit: true,
value: '',
editField: {
key: true
},
dynamicParamDefaultValue: {
inputType: 'reference',
valueType: 'string',
required: true
}
toolDescription: '绘图提示词'
}
],
outputs: [
{
id: 'mv52BrPVE6bm',
key: '飞书机器人地址',
valueType: 'string',
label: '飞书机器人地址',
type: 'static'
},
{
id: 'p0m68Dv5KaIp',
key: '发送的消息',
id: '绘图提示词',
valueType: 'string',
label: '发送的消息',
type: 'static'
key: '绘图提示词',
label: '绘图提示词',
type: 'hidden'
}
]
},
......@@ -3001,27 +3167,46 @@ export const pluginTemplates: TemplateType = [
nodeId: 'pluginOutput',
name: '自定义插件输出',
intro: '自定义配置外部输出,使用插件时,仅暴露自定义配置的输出',
avatar: '/imgs/workflow/output.png',
avatar: 'core/workflow/template/pluginOutput',
flowNodeType: 'pluginOutput',
showStatus: false,
position: {
x: 1668.9410524554828,
y: -153.47815316221283
x: 1983.6911708285384,
y: -95.86447885674228
},
version: '481',
inputs: [],
inputs: [
{
renderTypeList: ['reference'],
valueType: 'string',
canEdit: true,
key: '图片访问链接',
label: '图片访问链接',
description: '',
value: ['tMvel910bnrJ', 'pJXgWoTpPoMy']
},
{
renderTypeList: ['reference'],
valueType: 'object',
canEdit: true,
key: 'error',
label: '错误信息',
description: '',
value: ['tMvel910bnrJ', 'error']
}
],
outputs: []
},
{
nodeId: 'rKBYGQuYefae',
nodeId: 'tMvel910bnrJ',
name: 'HTTP 请求',
intro: '可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
avatar: 'core/workflow/template/httpRequest',
flowNodeType: 'httpRequest468',
showStatus: true,
position: {
x: 1069.7228495148624,
y: -392.26482361861054
x: 1138.1732435351091,
y: -416.6443415407282
},
version: '481',
inputs: [
......@@ -3031,33 +3216,27 @@ export const pluginTemplates: TemplateType = [
valueType: 'dynamic',
label: '',
required: false,
description: 'core.module.input.description.HTTP Dynamic Input'
},
{
key: 'text',
valueType: 'string',
label: 'text',
renderTypeList: ['reference'],
description: '',
canEdit: true,
editField: {
key: true,
valueType: true
},
value: ['pluginInput', 'p0m68Dv5KaIp']
},
{
key: 'url',
valueType: 'string',
label: 'url',
renderTypeList: ['reference'],
description: '',
canEdit: true,
editField: {
key: true,
valueType: true
},
value: ['pluginInput', 'mv52BrPVE6bm']
description: 'core.module.input.description.HTTP Dynamic Input',
customInputConfig: {
selectValueTypeList: [
'string',
'number',
'boolean',
'object',
'arrayString',
'arrayNumber',
'arrayBoolean',
'arrayObject',
'any',
'chatHistory',
'datasetQuote',
'dynamic',
'selectApp',
'selectDataset'
],
showDescription: false,
showDefaultValue: true
}
},
{
key: 'system_httpMethod',
......@@ -3075,13 +3254,19 @@ export const pluginTemplates: TemplateType = [
description: 'core.module.input.description.Http Request Url',
placeholder: 'https://api.ai.com/getInventory',
required: false,
value: '{{url}}'
value: 'https://fal.run/fal-ai/flux-pro'
},
{
key: 'system_httpHeader',
renderTypeList: ['custom'],
valueType: 'any',
value: [],
value: [
{
key: 'Authorization',
type: 'string',
value: 'Key {{apikey}}'
}
],
label: '',
description: 'core.module.input.description.Http Request Header',
placeholder: 'core.module.input.description.Http Request Header',
......@@ -3100,24 +3285,42 @@ export const pluginTemplates: TemplateType = [
renderTypeList: ['hidden'],
valueType: 'any',
value:
'{\r\n "msg_type": "text",\r\n "content": {\r\n "text": "{{text}}"\r\n }\r\n}',
'{\n "prompt": "{{prompt}}",\n "image_size": "landscape_4_3",\n "num_inference_steps": 28,\n "guidance_scale": 3.5\n}',
label: '',
required: false
},
{
renderTypeList: ['reference'],
valueType: 'string',
canEdit: true,
key: 'prompt',
label: 'prompt',
customInputConfig: {
selectValueTypeList: [
'string',
'number',
'boolean',
'object',
'arrayString',
'arrayNumber',
'arrayBoolean',
'arrayObject',
'any',
'chatHistory',
'datasetQuote',
'dynamic',
'selectApp',
'selectDataset'
],
showDescription: false,
showDefaultValue: true
},
required: true,
value: ['pluginInput', '绘图提示词']
}
],
outputs: [
{
id: 'system_addOutputParam',
key: 'system_addOutputParam',
type: 'dynamic',
valueType: 'dynamic',
label: '',
editField: {
key: true,
valueType: true
}
},
{
id: 'error',
key: 'error',
label: '请求错误',
......@@ -3133,6 +3336,40 @@ export const pluginTemplates: TemplateType = [
description: 'HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。',
valueType: 'any',
type: 'static'
},
{
id: 'system_addOutputParam',
key: 'system_addOutputParam',
type: 'dynamic',
valueType: 'dynamic',
label: '',
customFieldConfig: {
selectValueTypeList: [
'string',
'number',
'boolean',
'object',
'arrayString',
'arrayNumber',
'arrayBoolean',
'arrayObject',
'any',
'chatHistory',
'datasetQuote',
'dynamic',
'selectApp',
'selectDataset'
],
showDescription: false,
showDefaultValue: false
}
},
{
id: 'pJXgWoTpPoMy',
valueType: 'string',
type: 'dynamic',
key: 'images[0].url',
label: 'images[0].url'
}
]
}
......@@ -3140,14 +3377,14 @@ export const pluginTemplates: TemplateType = [
edges: [
{
source: 'pluginInput',
target: 'rKBYGQuYefae',
target: 'tMvel910bnrJ',
sourceHandle: 'pluginInput-source-right',
targetHandle: 'rKBYGQuYefae-target-left'
targetHandle: 'tMvel910bnrJ-target-left'
},
{
source: 'rKBYGQuYefae',
source: 'tMvel910bnrJ',
target: 'pluginOutput',
sourceHandle: 'rKBYGQuYefae-source-right',
sourceHandle: 'tMvel910bnrJ-source-right',
targetHandle: 'pluginOutput-target-left'
}
]
......
......@@ -2,12 +2,11 @@ import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node.d';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { getWebLLMModel } from '@/web/common/system/utils';
export function checkChatSupportSelectFileByChatModels(models: string[] = []) {
const llmModelList = useSystemStore.getState().llmModelList;
for (const model of models) {
const modelData = llmModelList.find((item) => item.model === model || item.name === model);
const modelData = getWebLLMModel(model);
if (modelData?.vision) {
return true;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment