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