mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-01 20:27:45 +00:00
v4.6.2-alpah (#511)
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import { TaskResponseKeyEnum } from '@fastgpt/global/core/chat/constants';
|
||||
import { sseResponseEventEnum } from '@fastgpt/service/common/response/constant';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { parseStreamChunk, SSEParseData } from '@/utils/sse';
|
||||
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/api.d';
|
||||
import { StartChatFnProps } from '@/components/ChatBox';
|
||||
import { getToken } from '@/web/support/user/auth';
|
||||
import { ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
|
||||
type StreamFetchProps = {
|
||||
url?: string;
|
||||
@@ -12,16 +12,17 @@ type StreamFetchProps = {
|
||||
onMessage: StartChatFnProps['generatingMessage'];
|
||||
abortSignal: AbortController;
|
||||
};
|
||||
type StreamResponseType = {
|
||||
responseText: string;
|
||||
[ModuleOutputKeyEnum.responseData]: ChatHistoryItemResType[];
|
||||
};
|
||||
export const streamFetch = ({
|
||||
url = '/api/v1/chat/completions',
|
||||
data,
|
||||
onMessage,
|
||||
abortSignal
|
||||
}: StreamFetchProps) =>
|
||||
new Promise<{
|
||||
responseText: string;
|
||||
[TaskResponseKeyEnum.responseData]: ChatHistoryItemResType[];
|
||||
}>(async (resolve, reject) => {
|
||||
new Promise<StreamResponseType>(async (resolve, reject) => {
|
||||
try {
|
||||
const response = await window.fetch(url, {
|
||||
method: 'POST',
|
||||
|
@@ -28,6 +28,16 @@ export const readTxtContent = (file: File) => {
|
||||
*/
|
||||
export const readPdfContent = (file: File) =>
|
||||
new Promise<string>((resolve, reject) => {
|
||||
type TokenType = {
|
||||
str: string;
|
||||
dir: string;
|
||||
width: number;
|
||||
height: number;
|
||||
transform: number[];
|
||||
fontName: string;
|
||||
hasEOL: boolean;
|
||||
};
|
||||
|
||||
try {
|
||||
const pdfjsLib = window['pdfjs-dist/build/pdf'];
|
||||
pdfjsLib.workerSrc = '/js/pdf.worker.js';
|
||||
@@ -36,9 +46,19 @@ export const readPdfContent = (file: File) =>
|
||||
const page = await doc.getPage(pageNo);
|
||||
const tokenizedText = await page.getTextContent();
|
||||
|
||||
const viewport = page.getViewport({ scale: 1 });
|
||||
const pageHeight = viewport.height;
|
||||
const headerThreshold = pageHeight * 0.07; // 假设页头在页面顶部5%的区域内
|
||||
const footerThreshold = pageHeight * 0.93; // 假设页脚在页面底部5%的区域内
|
||||
|
||||
const pageText = tokenizedText.items
|
||||
.map((token: any) => token.str)
|
||||
.filter((item: string) => item)
|
||||
.filter((token: TokenType) => {
|
||||
return (
|
||||
!token.transform ||
|
||||
(token.transform[5] > headerThreshold && token.transform[5] < footerThreshold)
|
||||
);
|
||||
})
|
||||
.map((token: TokenType) => token.str)
|
||||
.join('');
|
||||
return pageText;
|
||||
};
|
||||
@@ -54,7 +74,7 @@ export const readPdfContent = (file: File) =>
|
||||
pageTextPromises.push(readPDFPage(doc, pageNo));
|
||||
}
|
||||
const pageTexts = await Promise.all(pageTextPromises);
|
||||
resolve(pageTexts.join('\n'));
|
||||
resolve(pageTexts.join(''));
|
||||
} catch (err) {
|
||||
console.log(err, 'pdf load error');
|
||||
reject('解析 PDF 失败');
|
||||
|
@@ -51,7 +51,7 @@ export const useEditTitle = ({
|
||||
// eslint-disable-next-line react/display-name
|
||||
const EditModal = useCallback(
|
||||
({ maxLength = 30 }: { maxLength?: number }) => (
|
||||
<MyModal isOpen={isOpen} onClose={onClose} title={title}>
|
||||
<MyModal isOpen={isOpen} onClose={onClose} iconSrc="/imgs/modal/edit.svg" title={title}>
|
||||
<ModalBody>
|
||||
{!!tip && (
|
||||
<Box mb={2} color={'myGray.500'} fontSize={'sm'}>
|
||||
|
@@ -11,6 +11,7 @@ import {
|
||||
defaultVectorModels,
|
||||
defaultAudioSpeechModels
|
||||
} from '@fastgpt/global/core/ai/model';
|
||||
import { AppSimpleEditConfigTemplateType } from '@fastgpt/global/core/app/type';
|
||||
|
||||
export let feConfigs: FeConfigsType = {};
|
||||
export let priceMd = '';
|
||||
@@ -23,6 +24,7 @@ export let cqModelList = defaultCQModels;
|
||||
export let extractModelList = defaultExtractModels;
|
||||
export let qgModelList = defaultQGModels;
|
||||
export let audioSpeechModels = defaultAudioSpeechModels;
|
||||
export let simpleModeTemplates: AppSimpleEditConfigTemplateType[] = [];
|
||||
|
||||
let retryTimes = 3;
|
||||
|
||||
@@ -43,6 +45,8 @@ export const clientInitData = async (): Promise<InitDateResponse> => {
|
||||
priceMd = res.priceMd;
|
||||
systemVersion = res.systemVersion;
|
||||
|
||||
simpleModeTemplates = res.simpleModeTemplates;
|
||||
|
||||
return res;
|
||||
} catch (error) {
|
||||
retryTimes--;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { useState, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { AppTTSConfigType } from '@/types/app';
|
||||
import type { AppTTSConfigType } from '@fastgpt/global/core/module/type.d';
|
||||
import { TTSTypeEnum } from '@/constants/app';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useRouter } from 'next/router';
|
||||
|
@@ -1,602 +0,0 @@
|
||||
import type { AppTTSConfigType, VariableItemType } from '@/types/app';
|
||||
import { chatModelList } from '@/web/common/system/staticData';
|
||||
import type { ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
import {
|
||||
FlowNodeInputTypeEnum,
|
||||
FlowNodeTypeEnum,
|
||||
FlowNodeValTypeEnum,
|
||||
FlowNodeSpecialInputKeyEnum
|
||||
} from '@fastgpt/global/core/module/node/constant';
|
||||
import { SystemInputEnum } from '@/constants/app';
|
||||
import type { SelectedDatasetType } from '@fastgpt/global/core/module/api.d';
|
||||
import type { FlowNodeInputItemType } from '@fastgpt/global/core/module/node/type.d';
|
||||
import type { AIChatProps } from '@/types/core/aiChat';
|
||||
import { getGuideModule, splitGuideModule } from '@/global/core/app/modules/utils';
|
||||
|
||||
export type EditFormType = {
|
||||
chatModel: AIChatProps;
|
||||
dataset: {
|
||||
list: SelectedDatasetType;
|
||||
searchSimilarity: number;
|
||||
searchLimit: number;
|
||||
searchEmptyText: string;
|
||||
rerank: boolean;
|
||||
};
|
||||
guide: {
|
||||
welcome: {
|
||||
text: string;
|
||||
};
|
||||
};
|
||||
variables: VariableItemType[];
|
||||
questionGuide: boolean;
|
||||
tts: AppTTSConfigType;
|
||||
};
|
||||
export const getDefaultAppForm = (): EditFormType => {
|
||||
const defaultChatModel = chatModelList[0];
|
||||
|
||||
return {
|
||||
chatModel: {
|
||||
model: defaultChatModel?.model,
|
||||
systemPrompt: '',
|
||||
temperature: 0,
|
||||
[SystemInputEnum.isResponseAnswerText]: true,
|
||||
quotePrompt: '',
|
||||
quoteTemplate: '',
|
||||
maxToken: defaultChatModel ? defaultChatModel.maxResponse / 2 : 4000,
|
||||
frequency: 0.5,
|
||||
presence: -0.5
|
||||
},
|
||||
dataset: {
|
||||
list: [],
|
||||
searchSimilarity: 0.4,
|
||||
searchLimit: 5,
|
||||
searchEmptyText: '',
|
||||
rerank: false
|
||||
},
|
||||
guide: {
|
||||
welcome: {
|
||||
text: ''
|
||||
}
|
||||
},
|
||||
variables: [],
|
||||
questionGuide: false,
|
||||
tts: {
|
||||
type: 'web'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const appModules2Form = (modules: ModuleItemType[]) => {
|
||||
const defaultAppForm = getDefaultAppForm();
|
||||
const updateVal = ({
|
||||
formKey,
|
||||
inputs,
|
||||
key
|
||||
}: {
|
||||
formKey: string;
|
||||
inputs: FlowNodeInputItemType[];
|
||||
key: string;
|
||||
}) => {
|
||||
const propertyPath = formKey.split('.');
|
||||
let currentObj: any = defaultAppForm;
|
||||
for (let i = 0; i < propertyPath.length - 1; i++) {
|
||||
currentObj = currentObj[propertyPath[i]];
|
||||
}
|
||||
|
||||
const val =
|
||||
inputs.find((item) => item.key === key)?.value ||
|
||||
currentObj[propertyPath[propertyPath.length - 1]];
|
||||
|
||||
currentObj[propertyPath[propertyPath.length - 1]] = val;
|
||||
};
|
||||
|
||||
modules.forEach((module) => {
|
||||
if (module.flowType === FlowNodeTypeEnum.chatNode) {
|
||||
updateVal({
|
||||
formKey: 'chatModel.model',
|
||||
inputs: module.inputs,
|
||||
key: 'model'
|
||||
});
|
||||
updateVal({
|
||||
formKey: 'chatModel.temperature',
|
||||
inputs: module.inputs,
|
||||
key: 'temperature'
|
||||
});
|
||||
updateVal({
|
||||
formKey: 'chatModel.maxToken',
|
||||
inputs: module.inputs,
|
||||
key: 'maxToken'
|
||||
});
|
||||
updateVal({
|
||||
formKey: 'chatModel.systemPrompt',
|
||||
inputs: module.inputs,
|
||||
key: 'systemPrompt'
|
||||
});
|
||||
updateVal({
|
||||
formKey: 'chatModel.quoteTemplate',
|
||||
inputs: module.inputs,
|
||||
key: 'quoteTemplate'
|
||||
});
|
||||
updateVal({
|
||||
formKey: 'chatModel.quotePrompt',
|
||||
inputs: module.inputs,
|
||||
key: 'quotePrompt'
|
||||
});
|
||||
} else if (module.flowType === FlowNodeTypeEnum.datasetSearchNode) {
|
||||
updateVal({
|
||||
formKey: 'dataset.list',
|
||||
inputs: module.inputs,
|
||||
key: 'datasets'
|
||||
});
|
||||
updateVal({
|
||||
formKey: 'dataset.searchSimilarity',
|
||||
inputs: module.inputs,
|
||||
key: 'similarity'
|
||||
});
|
||||
updateVal({
|
||||
formKey: 'dataset.searchLimit',
|
||||
inputs: module.inputs,
|
||||
key: 'limit'
|
||||
});
|
||||
updateVal({
|
||||
formKey: 'dataset.rerank',
|
||||
inputs: module.inputs,
|
||||
key: 'rerank'
|
||||
});
|
||||
// empty text
|
||||
const emptyOutputs = module.outputs.find((item) => item.key === 'isEmpty')?.targets || [];
|
||||
const emptyOutput = emptyOutputs[0];
|
||||
if (emptyOutput) {
|
||||
const target = modules.find((item) => item.moduleId === emptyOutput.moduleId);
|
||||
defaultAppForm.dataset.searchEmptyText =
|
||||
target?.inputs?.find((item) => item.key === FlowNodeSpecialInputKeyEnum.answerText)
|
||||
?.value || '';
|
||||
}
|
||||
} else if (module.flowType === FlowNodeTypeEnum.userGuide) {
|
||||
const { welcomeText, variableModules, questionGuide, ttsConfig } = splitGuideModule(
|
||||
getGuideModule(modules)
|
||||
);
|
||||
if (welcomeText) {
|
||||
defaultAppForm.guide.welcome = {
|
||||
text: welcomeText
|
||||
};
|
||||
}
|
||||
|
||||
defaultAppForm.variables = variableModules;
|
||||
defaultAppForm.questionGuide = !!questionGuide;
|
||||
defaultAppForm.tts = ttsConfig;
|
||||
}
|
||||
});
|
||||
|
||||
return defaultAppForm;
|
||||
};
|
||||
|
||||
const chatModelInput = (formData: EditFormType): FlowNodeInputItemType[] => [
|
||||
{
|
||||
key: 'model',
|
||||
value: formData.chatModel.model,
|
||||
type: 'custom',
|
||||
label: '对话模型',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'temperature',
|
||||
value: formData.chatModel.temperature,
|
||||
type: 'slider',
|
||||
label: '温度',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'maxToken',
|
||||
value: formData.chatModel.maxToken,
|
||||
type: 'custom',
|
||||
label: '回复上限',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'systemPrompt',
|
||||
value: formData.chatModel.systemPrompt || '',
|
||||
type: 'textarea',
|
||||
label: '系统提示词',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: SystemInputEnum.isResponseAnswerText,
|
||||
value: true,
|
||||
type: 'hidden',
|
||||
label: '返回AI内容',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'quoteTemplate',
|
||||
value: formData.chatModel.quoteTemplate || '',
|
||||
type: 'hidden',
|
||||
label: '引用内容模板',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'quotePrompt',
|
||||
value: formData.chatModel.quotePrompt || '',
|
||||
type: 'hidden',
|
||||
label: '引用内容提示词',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'switch',
|
||||
type: 'target',
|
||||
label: '触发器',
|
||||
connected: formData.dataset.list.length > 0 && !!formData.dataset.searchEmptyText
|
||||
},
|
||||
{
|
||||
key: 'quoteQA',
|
||||
type: 'target',
|
||||
label: '引用内容',
|
||||
connected: formData.dataset.list.length > 0
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'target',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: 'target',
|
||||
label: '用户问题',
|
||||
connected: true
|
||||
}
|
||||
];
|
||||
const userGuideTemplate = (formData: EditFormType): ModuleItemType[] => [
|
||||
{
|
||||
name: '用户引导',
|
||||
flowType: FlowNodeTypeEnum.userGuide,
|
||||
inputs: [
|
||||
{
|
||||
key: SystemInputEnum.welcomeText,
|
||||
type: FlowNodeInputTypeEnum.hidden,
|
||||
label: '开场白',
|
||||
value: formData.guide.welcome.text
|
||||
},
|
||||
{
|
||||
key: SystemInputEnum.variables,
|
||||
type: FlowNodeInputTypeEnum.hidden,
|
||||
label: '对话框变量',
|
||||
value: formData.variables
|
||||
},
|
||||
{
|
||||
key: SystemInputEnum.questionGuide,
|
||||
type: FlowNodeInputTypeEnum.hidden,
|
||||
label: '问题引导',
|
||||
value: formData.questionGuide
|
||||
},
|
||||
{
|
||||
key: SystemInputEnum.tts,
|
||||
type: FlowNodeInputTypeEnum.hidden,
|
||||
label: '语音播报',
|
||||
value: formData.tts
|
||||
}
|
||||
],
|
||||
outputs: [],
|
||||
position: {
|
||||
x: 447.98520778293346,
|
||||
y: 721.4016845336229
|
||||
},
|
||||
moduleId: 'userGuide'
|
||||
}
|
||||
];
|
||||
const simpleChatTemplate = (formData: EditFormType): ModuleItemType[] => [
|
||||
{
|
||||
name: '用户问题(对话入口)',
|
||||
flowType: FlowNodeTypeEnum.questionInput,
|
||||
inputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
connected: true,
|
||||
label: '用户问题',
|
||||
type: 'target'
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'userChatInput'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
position: {
|
||||
x: 464.32198615344566,
|
||||
y: 1602.2698463081606
|
||||
},
|
||||
moduleId: 'userChatInput'
|
||||
},
|
||||
{
|
||||
name: '聊天记录',
|
||||
flowType: FlowNodeTypeEnum.historyNode,
|
||||
inputs: [
|
||||
{
|
||||
key: 'maxContext',
|
||||
value: 6,
|
||||
connected: true,
|
||||
type: 'numberInput',
|
||||
label: '最长记录数'
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'hidden',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'history',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'history'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
position: {
|
||||
x: 452.5466249541586,
|
||||
y: 1276.3930310334215
|
||||
},
|
||||
moduleId: 'history'
|
||||
},
|
||||
{
|
||||
name: 'AI 对话',
|
||||
flowType: FlowNodeTypeEnum.chatNode,
|
||||
inputs: chatModelInput(formData),
|
||||
showStatus: true,
|
||||
outputs: [
|
||||
{
|
||||
key: 'answerText',
|
||||
label: 'AI回复',
|
||||
description: '直接响应,无需配置',
|
||||
type: 'hidden',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'finish',
|
||||
label: '回复结束',
|
||||
description: 'AI 回复完成后触发',
|
||||
valueType: 'boolean',
|
||||
type: 'source',
|
||||
targets: []
|
||||
}
|
||||
],
|
||||
position: {
|
||||
x: 981.9682828103937,
|
||||
y: 890.014595014464
|
||||
},
|
||||
moduleId: 'chatModule'
|
||||
}
|
||||
];
|
||||
const kbTemplate = (formData: EditFormType): ModuleItemType[] => [
|
||||
{
|
||||
name: '用户问题(对话入口)',
|
||||
flowType: FlowNodeTypeEnum.questionInput,
|
||||
inputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
label: '用户问题',
|
||||
type: 'target',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'userChatInput'
|
||||
},
|
||||
{
|
||||
moduleId: 'datasetSearch',
|
||||
key: 'userChatInput'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
position: {
|
||||
x: 464.32198615344566,
|
||||
y: 1602.2698463081606
|
||||
},
|
||||
moduleId: 'userChatInput'
|
||||
},
|
||||
{
|
||||
name: '聊天记录',
|
||||
flowType: FlowNodeTypeEnum.historyNode,
|
||||
inputs: [
|
||||
{
|
||||
key: 'maxContext',
|
||||
value: 6,
|
||||
connected: true,
|
||||
type: 'numberInput',
|
||||
label: '最长记录数'
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'hidden',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'history',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'history'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
position: {
|
||||
x: 452.5466249541586,
|
||||
y: 1276.3930310334215
|
||||
},
|
||||
moduleId: 'history'
|
||||
},
|
||||
{
|
||||
name: '知识库搜索',
|
||||
flowType: FlowNodeTypeEnum.datasetSearchNode,
|
||||
showStatus: true,
|
||||
inputs: [
|
||||
{
|
||||
key: 'datasets',
|
||||
value: formData.dataset.list,
|
||||
type: FlowNodeInputTypeEnum.custom,
|
||||
label: '关联的知识库',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'similarity',
|
||||
value: formData.dataset.searchSimilarity,
|
||||
type: FlowNodeInputTypeEnum.slider,
|
||||
label: '相似度',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'limit',
|
||||
value: formData.dataset.searchLimit,
|
||||
type: FlowNodeInputTypeEnum.slider,
|
||||
label: '单次搜索上限',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'switch',
|
||||
type: FlowNodeInputTypeEnum.target,
|
||||
label: '触发器',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: FlowNodeInputTypeEnum.target,
|
||||
label: '用户问题',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'rerank',
|
||||
type: FlowNodeInputTypeEnum.switch,
|
||||
label: '结果重排',
|
||||
description: '将召回的结果进行进一步重排,可增加召回率',
|
||||
plusField: true,
|
||||
connected: true,
|
||||
value: formData.dataset.rerank
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'isEmpty',
|
||||
targets: formData.dataset.searchEmptyText
|
||||
? [
|
||||
{
|
||||
moduleId: 'emptyText',
|
||||
key: 'switch'
|
||||
}
|
||||
]
|
||||
: []
|
||||
},
|
||||
{
|
||||
key: 'unEmpty',
|
||||
targets: formData.dataset.searchEmptyText
|
||||
? [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'switch'
|
||||
}
|
||||
]
|
||||
: []
|
||||
},
|
||||
{
|
||||
key: 'quoteQA',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'quoteQA'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
position: {
|
||||
x: 956.0838440206068,
|
||||
y: 887.462827870246
|
||||
},
|
||||
moduleId: 'datasetSearch'
|
||||
},
|
||||
...(formData.dataset.searchEmptyText
|
||||
? [
|
||||
{
|
||||
name: '指定回复',
|
||||
flowType: FlowNodeTypeEnum.answerNode,
|
||||
inputs: [
|
||||
{
|
||||
key: 'switch',
|
||||
type: FlowNodeInputTypeEnum.target,
|
||||
label: '触发器',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: FlowNodeSpecialInputKeyEnum.answerText,
|
||||
value: formData.dataset.searchEmptyText,
|
||||
type: FlowNodeInputTypeEnum.textarea,
|
||||
valueType: FlowNodeValTypeEnum.string,
|
||||
label: '回复的内容',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [],
|
||||
position: {
|
||||
x: 1553.5815811529146,
|
||||
y: 637.8753731306779
|
||||
},
|
||||
moduleId: 'emptyText'
|
||||
}
|
||||
]
|
||||
: []),
|
||||
{
|
||||
name: 'AI 对话',
|
||||
flowType: FlowNodeTypeEnum.chatNode,
|
||||
inputs: chatModelInput(formData),
|
||||
showStatus: true,
|
||||
outputs: [
|
||||
{
|
||||
key: 'answerText',
|
||||
label: 'AI回复',
|
||||
description: '直接响应,无需配置',
|
||||
type: 'hidden',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'finish',
|
||||
label: '回复结束',
|
||||
description: 'AI 回复完成后触发',
|
||||
valueType: 'boolean',
|
||||
type: 'source',
|
||||
targets: []
|
||||
}
|
||||
],
|
||||
position: {
|
||||
x: 1551.71405495818,
|
||||
y: 977.4911578918461
|
||||
},
|
||||
moduleId: 'chatModule'
|
||||
}
|
||||
];
|
||||
|
||||
export const appForm2Modules = (formData: EditFormType) => {
|
||||
const modules = [
|
||||
...userGuideTemplate(formData),
|
||||
...(formData.dataset.list.length > 0 ? kbTemplate(formData) : simpleChatTemplate(formData))
|
||||
];
|
||||
|
||||
return modules as ModuleItemType[];
|
||||
};
|
1638
projects/app/src/web/core/app/templates.ts
Normal file
1638
projects/app/src/web/core/app/templates.ts
Normal file
File diff suppressed because it is too large
Load Diff
65
projects/app/src/web/core/app/utils.ts
Normal file
65
projects/app/src/web/core/app/utils.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { AppSimpleEditFormType } from '@fastgpt/global/core/app/type';
|
||||
import { ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
import { POST } from '@/web/common/api/request';
|
||||
import { chatModelList } from '@/web/common/system/staticData';
|
||||
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import type { FormatForm2ModulesProps } from '@fastgpt/global/core/app/api.d';
|
||||
|
||||
export async function postForm2Modules(
|
||||
data: AppSimpleEditFormType,
|
||||
templateId = 'fastgpt-universal'
|
||||
) {
|
||||
function userGuideTemplate(formData: AppSimpleEditFormType): ModuleItemType[] {
|
||||
return [
|
||||
{
|
||||
name: '用户引导',
|
||||
flowType: FlowNodeTypeEnum.userGuide,
|
||||
inputs: [
|
||||
{
|
||||
key: ModuleInputKeyEnum.welcomeText,
|
||||
type: FlowNodeInputTypeEnum.hidden,
|
||||
label: '开场白',
|
||||
value: formData.userGuide.welcomeText
|
||||
},
|
||||
{
|
||||
key: ModuleInputKeyEnum.variables,
|
||||
type: FlowNodeInputTypeEnum.hidden,
|
||||
label: '对话框变量',
|
||||
value: formData.userGuide.variables
|
||||
},
|
||||
{
|
||||
key: ModuleInputKeyEnum.questionGuide,
|
||||
type: FlowNodeInputTypeEnum.hidden,
|
||||
label: '问题引导',
|
||||
value: formData.userGuide.questionGuide
|
||||
},
|
||||
{
|
||||
key: ModuleInputKeyEnum.tts,
|
||||
type: FlowNodeInputTypeEnum.hidden,
|
||||
label: '语音播报',
|
||||
value: formData.userGuide.tts
|
||||
}
|
||||
],
|
||||
outputs: [],
|
||||
position: {
|
||||
x: 447.98520778293346,
|
||||
y: 721.4016845336229
|
||||
},
|
||||
moduleId: 'userGuide'
|
||||
}
|
||||
];
|
||||
}
|
||||
const maxToken =
|
||||
chatModelList.find((item) => item.model === data.aiSettings.model)?.maxResponse || 4000;
|
||||
|
||||
const props: FormatForm2ModulesProps = {
|
||||
formData: data,
|
||||
chatModelMaxToken: maxToken,
|
||||
chatModelList
|
||||
};
|
||||
|
||||
const modules = await POST<ModuleItemType[]>(`/core/app/form2Modules/${templateId}`, props);
|
||||
|
||||
return [...userGuideTemplate(data), ...modules];
|
||||
}
|
@@ -104,98 +104,99 @@ const SelectCollections = ({
|
||||
w={'100%'}
|
||||
h={['90vh', '80vh']}
|
||||
isCentered
|
||||
iconSrc="/imgs/modal/move.svg"
|
||||
title={
|
||||
<Box>
|
||||
<ParentPaths
|
||||
paths={paths.map((path, i) => ({
|
||||
parentId: path.parentId,
|
||||
parentName: path.parentName
|
||||
}))}
|
||||
FirstPathDom={
|
||||
<>
|
||||
<Box fontWeight={'bold'} fontSize={['sm', 'lg']}>
|
||||
{title || type === 'folder'
|
||||
? t('common.Select One Folder')
|
||||
: t('dataset.collections.Select Collection')}
|
||||
</Box>
|
||||
{!!tip && (
|
||||
<Box fontSize={'sm'} color={'myGray.500'}>
|
||||
{tip}
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
onClick={(e) => {
|
||||
setParentId(e);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Flex flexDirection={'column'} flex={'1 0 0'}>
|
||||
<Box flex={'1 0 0'} px={4} py={2}>
|
||||
<Flex flexDirection={'column'} h={'100%'} position={'relative'}>
|
||||
<Box>
|
||||
<ParentPaths
|
||||
paths={paths.map((path, i) => ({
|
||||
parentId: path.parentId,
|
||||
parentName: path.parentName
|
||||
}))}
|
||||
FirstPathDom={
|
||||
<>
|
||||
<Box fontWeight={'bold'} fontSize={['sm', 'lg']}>
|
||||
{title || type === 'folder'
|
||||
? t('common.Select One Folder')
|
||||
: t('dataset.collections.Select Collection')}
|
||||
</Box>
|
||||
{!!tip && (
|
||||
<Box fontSize={'sm'} color={'myGray.500'}>
|
||||
{tip}
|
||||
<Box flex={'1 0 0'} px={4} py={2} position={'relative'}>
|
||||
<Grid
|
||||
gridTemplateColumns={['repeat(1,1fr)', 'repeat(2,1fr)', 'repeat(3,1fr)']}
|
||||
gridGap={3}
|
||||
userSelect={'none'}
|
||||
overflowY={'auto'}
|
||||
mt={2}
|
||||
>
|
||||
{collections.map((item) =>
|
||||
(() => {
|
||||
const selected = selectedDatasetCollectionIds.includes(item._id);
|
||||
return (
|
||||
<Card
|
||||
key={item._id}
|
||||
p={3}
|
||||
border={theme.borders.base}
|
||||
boxShadow={'sm'}
|
||||
cursor={'pointer'}
|
||||
_hover={{
|
||||
boxShadow: 'md'
|
||||
}}
|
||||
{...(selected
|
||||
? {
|
||||
bg: 'myBlue.300'
|
||||
}
|
||||
: {})}
|
||||
onClick={() => {
|
||||
if (item.type === DatasetCollectionTypeEnum.folder) {
|
||||
setParentId(item._id);
|
||||
} else {
|
||||
let result: string[] = [];
|
||||
if (max === 1) {
|
||||
result = [item._id];
|
||||
} else if (selected) {
|
||||
result = selectedDatasetCollectionIds.filter((id) => id !== item._id);
|
||||
} else if (selectedDatasetCollectionIds.length < max) {
|
||||
result = [...selectedDatasetCollectionIds, item._id];
|
||||
}
|
||||
setSelectedDatasetCollectionIds(result);
|
||||
onChange && onChange({ parentId, collectionIds: result });
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Flex alignItems={'center'} h={'38px'}>
|
||||
<Image src={item.icon} w={'18px'} alt={''} />
|
||||
<Box ml={3} fontSize={'sm'}>
|
||||
{item.name}
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
onClick={(e) => {
|
||||
setParentId(e);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box flex={'1 0 0'} overflowY={'auto'} mt={2}>
|
||||
<Grid
|
||||
gridTemplateColumns={['repeat(1,1fr)', 'repeat(2,1fr)', 'repeat(3,1fr)']}
|
||||
gridGap={3}
|
||||
userSelect={'none'}
|
||||
>
|
||||
{collections.map((item) =>
|
||||
(() => {
|
||||
const selected = selectedDatasetCollectionIds.includes(item._id);
|
||||
return (
|
||||
<Card
|
||||
key={item._id}
|
||||
p={3}
|
||||
border={theme.borders.base}
|
||||
boxShadow={'sm'}
|
||||
cursor={'pointer'}
|
||||
_hover={{
|
||||
boxShadow: 'md'
|
||||
}}
|
||||
{...(selected
|
||||
? {
|
||||
bg: 'myBlue.300'
|
||||
}
|
||||
: {})}
|
||||
onClick={() => {
|
||||
if (item.type === DatasetCollectionTypeEnum.folder) {
|
||||
setParentId(item._id);
|
||||
} else {
|
||||
let result: string[] = [];
|
||||
if (max === 1) {
|
||||
result = [item._id];
|
||||
} else if (selected) {
|
||||
result = selectedDatasetCollectionIds.filter((id) => id !== item._id);
|
||||
} else if (selectedDatasetCollectionIds.length < max) {
|
||||
result = [...selectedDatasetCollectionIds, item._id];
|
||||
}
|
||||
setSelectedDatasetCollectionIds(result);
|
||||
onChange && onChange({ parentId, collectionIds: result });
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Flex alignItems={'center'} h={'38px'}>
|
||||
<Image src={item.icon} w={'18px'} alt={''} />
|
||||
<Box ml={3} fontSize={'sm'}>
|
||||
{item.name}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Card>
|
||||
);
|
||||
})()
|
||||
)}
|
||||
</Grid>
|
||||
{collections.length === 0 && (
|
||||
<Flex mt={'10vh'} flexDirection={'column'} alignItems={'center'}>
|
||||
<MyIcon name="empty" w={'48px'} h={'48px'} color={'transparent'} />
|
||||
<Box mt={2} color={'myGray.500'}>
|
||||
{t('common.folder.No Folder')}
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
</Box>
|
||||
<Loading loading={isLoading} fixed={false} />
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Card>
|
||||
);
|
||||
})()
|
||||
)}
|
||||
</Grid>
|
||||
{collections.length === 0 && (
|
||||
<Flex mt={'20vh'} flexDirection={'column'} alignItems={'center'}>
|
||||
<MyIcon name="empty" w={'48px'} h={'48px'} color={'transparent'} />
|
||||
<Box mt={2} color={'myGray.500'}>
|
||||
{t('common.folder.No Folder')}
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
<Loading loading={isLoading} fixed={false} />
|
||||
</Box>
|
||||
{CustomFooter ? (
|
||||
<>{CustomFooter}</>
|
||||
|
82
projects/app/src/web/core/modules/constants/dataType.ts
Normal file
82
projects/app/src/web/core/modules/constants/dataType.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import type { BoxProps } from '@chakra-ui/react';
|
||||
import { ModuleDataTypeEnum } from '@fastgpt/global/core/module/constants';
|
||||
|
||||
export const FlowValueTypeStyle: Record<`${ModuleDataTypeEnum}`, BoxProps> = {
|
||||
[ModuleDataTypeEnum.string]: {
|
||||
background: '#36ADEF'
|
||||
},
|
||||
[ModuleDataTypeEnum.number]: {
|
||||
background: '#FB7C3C'
|
||||
},
|
||||
[ModuleDataTypeEnum.boolean]: {
|
||||
background: '#E7D118'
|
||||
},
|
||||
[ModuleDataTypeEnum.chatHistory]: {
|
||||
background: '#00A9A6'
|
||||
},
|
||||
[ModuleDataTypeEnum.datasetQuote]: {
|
||||
background: '#A558C9'
|
||||
},
|
||||
[ModuleDataTypeEnum.any]: {
|
||||
background: '#9CA2A8'
|
||||
},
|
||||
[ModuleDataTypeEnum.selectApp]: {
|
||||
background: '#6a6efa'
|
||||
},
|
||||
[ModuleDataTypeEnum.selectDataset]: {
|
||||
background: '#21ba45'
|
||||
}
|
||||
};
|
||||
export const FlowValueTypeMap = {
|
||||
[ModuleDataTypeEnum.string]: {
|
||||
label: 'core.module.valueType.string',
|
||||
value: ModuleDataTypeEnum.string,
|
||||
example: ''
|
||||
},
|
||||
[ModuleDataTypeEnum.number]: {
|
||||
label: 'core.module.valueType.number',
|
||||
value: ModuleDataTypeEnum.number,
|
||||
example: ''
|
||||
},
|
||||
[ModuleDataTypeEnum.boolean]: {
|
||||
label: 'core.module.valueType.boolean',
|
||||
value: ModuleDataTypeEnum.boolean,
|
||||
example: ''
|
||||
},
|
||||
[ModuleDataTypeEnum.chatHistory]: {
|
||||
label: 'core.module.valueType.chatHistory',
|
||||
value: ModuleDataTypeEnum.chatHistory,
|
||||
example: `{
|
||||
obj: System | Human | AI;
|
||||
value: string;
|
||||
}`
|
||||
},
|
||||
[ModuleDataTypeEnum.datasetQuote]: {
|
||||
label: 'core.module.valueType.datasetQuote',
|
||||
value: ModuleDataTypeEnum.datasetQuote,
|
||||
example: `{
|
||||
id: string;
|
||||
datasetId: string;
|
||||
collectionId: string;
|
||||
sourceName: string;
|
||||
sourceId?: string;
|
||||
q: string;
|
||||
a: string
|
||||
}`
|
||||
},
|
||||
[ModuleDataTypeEnum.any]: {
|
||||
label: 'core.module.valueType.any',
|
||||
value: ModuleDataTypeEnum.any,
|
||||
example: ''
|
||||
},
|
||||
[ModuleDataTypeEnum.selectApp]: {
|
||||
label: 'core.module.valueType.selectApp',
|
||||
value: ModuleDataTypeEnum.selectApp,
|
||||
example: ''
|
||||
},
|
||||
[ModuleDataTypeEnum.selectDataset]: {
|
||||
label: 'core.module.valueType.selectDataset',
|
||||
value: ModuleDataTypeEnum.selectDataset,
|
||||
example: ''
|
||||
}
|
||||
};
|
7
projects/app/src/web/core/modules/constants/flowUi.ts
Normal file
7
projects/app/src/web/core/modules/constants/flowUi.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const edgeOptions = {
|
||||
style: {
|
||||
strokeWidth: 1.5,
|
||||
stroke: '#5A646Es'
|
||||
}
|
||||
};
|
||||
export const connectionLineStyle = { strokeWidth: 1.5, stroke: '#5A646Es' };
|
153
projects/app/src/web/core/modules/template/system.ts
Normal file
153
projects/app/src/web/core/modules/template/system.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import { UserGuideModule } from '@fastgpt/global/core/module/template/system/userGuide';
|
||||
import { UserInputModule } from '@fastgpt/global/core/module/template/system/userInput';
|
||||
import { HistoryModule } from '@fastgpt/global/core/module/template/system/history';
|
||||
import { AiChatModule } from '@fastgpt/global/core/module/template/system/aiChat';
|
||||
import { DatasetSearchModule } from '@fastgpt/global/core/module/template/system/datasetSearch';
|
||||
import { AssignedAnswerModule } from '@fastgpt/global/core/module/template/system/assignedAnswer';
|
||||
import { ClassifyQuestionModule } from '@fastgpt/global/core/module/template/system/classifyQuestion';
|
||||
import { ContextExtractModule } from '@fastgpt/global/core/module/template/system/contextExtract';
|
||||
import { HttpModule } from '@fastgpt/global/core/module/template/system/http';
|
||||
import { EmptyModule } from '@fastgpt/global/core/module/template/system/empty';
|
||||
import { RunAppModule } from '@fastgpt/global/core/module/template/system/runApp';
|
||||
import { PluginInputModule } from '@fastgpt/global/core/module/template/system/pluginInput';
|
||||
import { PluginOutputModule } from '@fastgpt/global/core/module/template/system/pluginOutput';
|
||||
import { RunPluginModule } from '@fastgpt/global/core/module/template/system/runPlugin';
|
||||
import type {
|
||||
FlowModuleTemplateType,
|
||||
moduleTemplateListType
|
||||
} from '@fastgpt/global/core/module/type.d';
|
||||
import { ModuleTemplateTypeEnum } from '@fastgpt/global/core/module/constants';
|
||||
|
||||
export const appSystemModuleTemplates: FlowModuleTemplateType[] = [
|
||||
UserGuideModule,
|
||||
UserInputModule,
|
||||
HistoryModule,
|
||||
AiChatModule,
|
||||
AssignedAnswerModule,
|
||||
DatasetSearchModule,
|
||||
RunAppModule,
|
||||
ClassifyQuestionModule,
|
||||
ContextExtractModule,
|
||||
HttpModule
|
||||
];
|
||||
export const pluginSystemModuleTemplates: FlowModuleTemplateType[] = [
|
||||
PluginInputModule,
|
||||
PluginOutputModule,
|
||||
HistoryModule,
|
||||
AiChatModule,
|
||||
AssignedAnswerModule,
|
||||
DatasetSearchModule,
|
||||
RunAppModule,
|
||||
ClassifyQuestionModule,
|
||||
ContextExtractModule,
|
||||
HttpModule
|
||||
];
|
||||
export const moduleTemplatesFlat: FlowModuleTemplateType[] = [
|
||||
UserGuideModule,
|
||||
UserInputModule,
|
||||
HistoryModule,
|
||||
AiChatModule,
|
||||
DatasetSearchModule,
|
||||
AssignedAnswerModule,
|
||||
ClassifyQuestionModule,
|
||||
ContextExtractModule,
|
||||
HttpModule,
|
||||
EmptyModule,
|
||||
RunAppModule,
|
||||
PluginInputModule,
|
||||
PluginOutputModule,
|
||||
RunPluginModule
|
||||
];
|
||||
|
||||
export const moduleTemplatesList: moduleTemplateListType = [
|
||||
{
|
||||
type: ModuleTemplateTypeEnum.userGuide,
|
||||
label: '引导模块',
|
||||
list: []
|
||||
},
|
||||
{
|
||||
type: ModuleTemplateTypeEnum.systemInput,
|
||||
label: '系统输入',
|
||||
list: []
|
||||
},
|
||||
{
|
||||
type: ModuleTemplateTypeEnum.textAnswer,
|
||||
label: '文本输出',
|
||||
list: []
|
||||
},
|
||||
{
|
||||
type: ModuleTemplateTypeEnum.dataset,
|
||||
label: '知识库',
|
||||
list: []
|
||||
},
|
||||
{
|
||||
type: ModuleTemplateTypeEnum.functionCall,
|
||||
label: '函数调用',
|
||||
list: []
|
||||
},
|
||||
{
|
||||
type: ModuleTemplateTypeEnum.externalCall,
|
||||
label: '外部调用',
|
||||
list: []
|
||||
},
|
||||
{
|
||||
type: ModuleTemplateTypeEnum.personalPlugin,
|
||||
label: '个人插件',
|
||||
list: []
|
||||
},
|
||||
{
|
||||
type: ModuleTemplateTypeEnum.communityPlugin,
|
||||
label: '社区插件',
|
||||
list: []
|
||||
},
|
||||
{
|
||||
type: ModuleTemplateTypeEnum.commercialPlugin,
|
||||
label: '商业插件',
|
||||
list: []
|
||||
},
|
||||
{
|
||||
type: ModuleTemplateTypeEnum.other,
|
||||
label: '其他',
|
||||
list: []
|
||||
}
|
||||
];
|
||||
// export const appSystemModuleTemplates = [
|
||||
// {
|
||||
// label: '引导模块',
|
||||
// list: [UserGuideModule]
|
||||
// },
|
||||
// {
|
||||
// label: '输入模块',
|
||||
// list: [UserInputModule, HistoryModule]
|
||||
// },
|
||||
// {
|
||||
// label: '内容生成',
|
||||
// list: [AiChatModule, AssignedAnswerModule]
|
||||
// },
|
||||
// {
|
||||
// label: '核心调用',
|
||||
// list: [DatasetSearchModule, RunAppModule]
|
||||
// },
|
||||
// {
|
||||
// label: '函数模块',
|
||||
// list: [ClassifyQuestionModule, ContextExtractModule, HttpModule]
|
||||
// }
|
||||
// ];
|
||||
// export const pluginModuleTemplates = [
|
||||
// {
|
||||
// label: '输入输出',
|
||||
// list: [PluginInputModule, PluginOutputModule, HistoryModule]
|
||||
// },
|
||||
// {
|
||||
// label: '内容生成',
|
||||
// list: [AiChatModule, AssignedAnswerModule]
|
||||
// },
|
||||
// {
|
||||
// label: '核心调用',
|
||||
// list: [DatasetSearchModule, RunAppModule]
|
||||
// },
|
||||
// {
|
||||
// label: '函数模块',
|
||||
// list: [ClassifyQuestionModule, ContextExtractModule, HttpModule]
|
||||
// }
|
||||
// ];
|
@@ -11,9 +11,8 @@ export const postCreatePlugin = (data: CreateOnePluginParams) =>
|
||||
POST<string>('/core/plugin/create', data);
|
||||
export const putUpdatePlugin = (data: UpdatePluginParams) => PUT('/core/plugin/update', data);
|
||||
export const getUserPlugins = () => GET<PluginListItemType[]>('/core/plugin/list');
|
||||
export const getUserPlugs2ModuleTemplates = () =>
|
||||
GET<FlowModuleTemplateType[]>('/core/plugin/templateList');
|
||||
export const getPluginModuleDetail = (id: string) =>
|
||||
GET<FlowModuleTemplateType>('/core/plugin/moduleDetail', { id });
|
||||
export const getPlugTemplates = () => GET<FlowModuleTemplateType[]>('/core/plugin/templates');
|
||||
export const getPreviewPluginModule = (id: string) =>
|
||||
GET<FlowModuleTemplateType>('/core/plugin/getPreviewModule', { id });
|
||||
export const getOnePlugin = (id: string) => GET<PluginItemSchema>('/core/plugin/detail', { id });
|
||||
export const delOnePlugin = (id: string) => DELETE('/core/plugin/delete', { id });
|
||||
|
@@ -1,23 +1,23 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import type { FlowModuleTemplateType } from '@fastgpt/global/core/module/type';
|
||||
import { getUserPlugs2ModuleTemplates } from '../api';
|
||||
import { getPlugTemplates } from '../api';
|
||||
import { FlowModuleTemplateType } from '@fastgpt/global/core/module/type';
|
||||
|
||||
type State = {
|
||||
pluginModuleTemplates: FlowModuleTemplateType[];
|
||||
loadPluginModuleTemplates: (init?: boolean) => Promise<FlowModuleTemplateType[]>;
|
||||
loadPluginTemplates: (init?: boolean) => Promise<FlowModuleTemplateType[]>;
|
||||
};
|
||||
|
||||
export const usePluginStore = create<State>()(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
pluginModuleTemplates: [],
|
||||
async loadPluginModuleTemplates(init) {
|
||||
async loadPluginTemplates(init) {
|
||||
if (!init && get().pluginModuleTemplates.length > 0) {
|
||||
return get().pluginModuleTemplates;
|
||||
}
|
||||
const templates = await getUserPlugs2ModuleTemplates();
|
||||
const templates = await getPlugTemplates();
|
||||
set((state) => {
|
||||
state.pluginModuleTemplates = templates;
|
||||
});
|
||||
|
@@ -4,7 +4,11 @@ import type { ResLogin } from '@/global/support/api/userRes.d';
|
||||
import { UserAuthTypeEnum } from '@/constants/common';
|
||||
import { UserUpdateParams } from '@/types/user';
|
||||
import { UserType } from '@fastgpt/global/support/user/type.d';
|
||||
import type { OauthLoginProps, PostLoginProps } from '@fastgpt/global/support/user/api.d';
|
||||
import type {
|
||||
FastLoginProps,
|
||||
OauthLoginProps,
|
||||
PostLoginProps
|
||||
} from '@fastgpt/global/support/user/api.d';
|
||||
|
||||
export const sendAuthCode = (data: {
|
||||
username: string;
|
||||
@@ -16,6 +20,8 @@ export const getTokenLogin = () =>
|
||||
GET<UserType>('/user/account/tokenLogin', {}, { maxQuantity: 1 });
|
||||
export const oauthLogin = (params: OauthLoginProps) =>
|
||||
POST<ResLogin>('/plusApi/support/user/account/login/oauth', params);
|
||||
export const postFastLogin = (params: FastLoginProps) =>
|
||||
POST<ResLogin>('/plusApi/support/user/account/login/fastLogin', params);
|
||||
|
||||
export const postRegister = ({
|
||||
username,
|
||||
|
Reference in New Issue
Block a user