mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-01 03:48:24 +00:00
4.7-alpha2 (#1027)
* feat: stop toolCall and rename some field. (#46) * perf: node delete tip;pay tip * fix: toolCall cannot save child answer * feat: stop tool * fix: team modal * fix feckbackMoal auth bug (#47) * 简单的支持提示词运行tool。优化workflow模板 (#49) * remove templates * fix: request body undefined * feat: prompt tool run * feat: workflow tamplates modal * perf: plugin start * 4.7 (#50) * fix docker-compose download url (#994) original code is a bad url with '404 NOT FOUND' return. fix docker-compose download url, add 'v' before docker-compose version * Update ai_settings.md (#1000) * Update configuration.md * Update configuration.md * Fix history in classifyQuestion and extract modules (#1012) * Fix history in classifyQuestion and extract modules * Add chatValue2RuntimePrompt import and update text formatting * flow controller to packages * fix: rerank select * modal ui * perf: modal code path * point not sufficient * feat: http url support variable * fix http key * perf: prompt * perf: ai setting modal * simple edit ui --------- Co-authored-by: entorick <entorick11@qq.com> Co-authored-by: liujianglc <liujianglc@163.com> Co-authored-by: Fengrui Liu <liufengrui.work@bytedance.com> * fix team share redirect to login (#51) * feat: support openapi import plugins (#48) * feat: support openapi import plugins * feat: import from url * fix: add body params parse * fix build * fix * fix * fix * tool box ui (#52) * fix: training queue * feat: simple edit tool select * perf: simple edit dataset prompt * fix: chatbox tool ux * feat: quote prompt module * perf: plugin tools sign * perf: model avatar * tool selector ui * feat: max histories * perf: http plugin import (#53) * perf: plugin http import * chatBox ui * perf: name * fix: Node template card (#54) * fix: ts * setting modal * package * package * feat: add plugins search (#57) * feat: add plugins search * perf: change http plugin header input * Yjl (#56) * perf: prompt tool call * perf: chat box ux * doc * doc * price tip * perf: tool selector * ui' * fix: vector queue * fix: empty tool and empty response * fix: empty msg * perf: pg index * perf: ui tip * doc * tool tip --------- Co-authored-by: yst <77910600+yu-and-liu@users.noreply.github.com> Co-authored-by: entorick <entorick11@qq.com> Co-authored-by: liujianglc <liujianglc@163.com> Co-authored-by: Fengrui Liu <liufengrui.work@bytedance.com> Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
@@ -10,6 +10,8 @@ import {
|
||||
EventStreamContentType,
|
||||
fetchEventSource
|
||||
} from '@fortaine/fetch-event-source';
|
||||
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
||||
import { useSystemStore } from '../system/useSystemStore';
|
||||
|
||||
type StreamFetchProps = {
|
||||
url?: string;
|
||||
@@ -34,13 +36,22 @@ export const streamFetch = ({
|
||||
|
||||
// response data
|
||||
let responseText = '';
|
||||
let remainTextList: { event: `${SseResponseEventEnum}`; text: string }[] = [];
|
||||
let errMsg = '';
|
||||
let responseQueue: (
|
||||
| { event: SseResponseEventEnum.fastAnswer | SseResponseEventEnum.answer; text: string }
|
||||
| {
|
||||
event:
|
||||
| SseResponseEventEnum.toolCall
|
||||
| SseResponseEventEnum.toolParams
|
||||
| SseResponseEventEnum.toolResponse;
|
||||
[key: string]: any;
|
||||
}
|
||||
)[] = [];
|
||||
let errMsg: string | undefined;
|
||||
let responseData: ChatHistoryItemResType[] = [];
|
||||
let finished = false;
|
||||
|
||||
const finish = () => {
|
||||
if (errMsg) {
|
||||
if (errMsg !== undefined) {
|
||||
return failedFinish();
|
||||
}
|
||||
return resolve({
|
||||
@@ -51,39 +62,41 @@ export const streamFetch = ({
|
||||
const failedFinish = (err?: any) => {
|
||||
finished = true;
|
||||
reject({
|
||||
message: getErrText(err, errMsg || '响应过程出现异常~'),
|
||||
message: getErrText(err, errMsg ?? '响应过程出现异常~'),
|
||||
responseText
|
||||
});
|
||||
};
|
||||
|
||||
const isAnswerEvent = (event: `${SseResponseEventEnum}`) =>
|
||||
event === SseResponseEventEnum.answer || event === SseResponseEventEnum.fastAnswer;
|
||||
// animate response to make it looks smooth
|
||||
function animateResponseText() {
|
||||
// abort message
|
||||
if (abortCtrl.signal.aborted) {
|
||||
remainTextList.forEach((item) => {
|
||||
responseQueue.forEach((item) => {
|
||||
onMessage(item);
|
||||
if (item.event === SseResponseEventEnum.answer) {
|
||||
if (isAnswerEvent(item.event)) {
|
||||
responseText += item.text;
|
||||
}
|
||||
});
|
||||
return finish();
|
||||
}
|
||||
|
||||
if (remainTextList.length > 0) {
|
||||
const fetchCount = Math.max(1, Math.round(remainTextList.length / 60));
|
||||
if (responseQueue.length > 0) {
|
||||
const fetchCount = Math.max(1, Math.round(responseQueue.length / 10));
|
||||
|
||||
for (let i = 0; i < fetchCount; i++) {
|
||||
const item = remainTextList[i];
|
||||
const item = responseQueue[i];
|
||||
onMessage(item);
|
||||
if (item.event === SseResponseEventEnum.answer) {
|
||||
if (isAnswerEvent(item.event)) {
|
||||
responseText += item.text;
|
||||
}
|
||||
}
|
||||
|
||||
remainTextList = remainTextList.slice(fetchCount);
|
||||
responseQueue = responseQueue.slice(fetchCount);
|
||||
}
|
||||
|
||||
if (finished && remainTextList.length === 0) {
|
||||
if (finished && responseQueue.length === 0) {
|
||||
return finish();
|
||||
}
|
||||
|
||||
@@ -153,28 +166,23 @@ export const streamFetch = ({
|
||||
return {};
|
||||
}
|
||||
})();
|
||||
|
||||
if (event === SseResponseEventEnum.answer) {
|
||||
const text: string = parseJson?.choices?.[0]?.delta?.content || '';
|
||||
|
||||
for (const item of text) {
|
||||
remainTextList.push({
|
||||
event,
|
||||
text: item
|
||||
});
|
||||
}
|
||||
} else if (event === SseResponseEventEnum.fastAnswer) {
|
||||
const text: string = parseJson?.choices?.[0]?.delta?.content || '';
|
||||
remainTextList.push({
|
||||
// console.log(parseJson, event);
|
||||
if (event === SseResponseEventEnum.answer || event === SseResponseEventEnum.fastAnswer) {
|
||||
const text = parseJson.choices?.[0]?.delta?.content || '';
|
||||
responseQueue.push({
|
||||
event,
|
||||
text
|
||||
});
|
||||
} else if (
|
||||
event === SseResponseEventEnum.flowNodeStatus ||
|
||||
event === SseResponseEventEnum.toolCall ||
|
||||
event === SseResponseEventEnum.toolParams ||
|
||||
event === SseResponseEventEnum.toolResponse
|
||||
) {
|
||||
responseQueue.push({
|
||||
event,
|
||||
...parseJson
|
||||
});
|
||||
} else if (event === SseResponseEventEnum.flowNodeStatus) {
|
||||
onMessage({
|
||||
event,
|
||||
...parseJson
|
||||
@@ -182,6 +190,9 @@ export const streamFetch = ({
|
||||
} else if (event === SseResponseEventEnum.flowResponses && Array.isArray(parseJson)) {
|
||||
responseData = parseJson;
|
||||
} else if (event === SseResponseEventEnum.error) {
|
||||
if (parseJson.statusText === TeamErrEnum.aiPointsNotEnough) {
|
||||
useSystemStore.getState().setIsNotSufficientModal(true);
|
||||
}
|
||||
errMsg = getErrText(parseJson, '流响应错误');
|
||||
}
|
||||
},
|
||||
|
@@ -6,6 +6,8 @@ import axios, {
|
||||
} from 'axios';
|
||||
import { clearToken, getToken } from '@/web/support/user/auth';
|
||||
import { TOKEN_ERROR_CODE } from '@fastgpt/global/common/error/errorCode';
|
||||
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
||||
import { useSystemStore } from '../system/useSystemStore';
|
||||
|
||||
interface ConfigType {
|
||||
headers?: { [key: string]: string };
|
||||
@@ -100,7 +102,9 @@ function responseError(err: any) {
|
||||
if (err?.code in TOKEN_ERROR_CODE) {
|
||||
clearToken();
|
||||
|
||||
if (window.location.pathname !== '/chat/share') {
|
||||
if (
|
||||
!(window.location.pathname === '/chat/share' || window.location.pathname === '/chat/team')
|
||||
) {
|
||||
window.location.replace(
|
||||
`/login?lastRoute=${encodeURIComponent(location.pathname + location.search)}`
|
||||
);
|
||||
@@ -108,6 +112,10 @@ function responseError(err: any) {
|
||||
|
||||
return Promise.reject({ message: '无权操作' });
|
||||
}
|
||||
if (err?.statusText === TeamErrEnum.aiPointsNotEnough) {
|
||||
useSystemStore.getState().setIsNotSufficientModal(true);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
if (err?.response?.data) {
|
||||
return Promise.reject(err?.response?.data);
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useDisclosure, Button, ModalBody, ModalFooter } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
|
||||
export const useConfirm = (props?: {
|
||||
title?: string;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
import { ModalFooter, ModalBody, Input, useDisclosure, Button, Box } from '@chakra-ui/react';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
|
@@ -24,11 +24,16 @@ export const useRequest = ({ successToast, errorToast, onSuccess, onError, ...pr
|
||||
},
|
||||
onError(err: any, variables: void, context: unknown) {
|
||||
onError?.(err, variables, context);
|
||||
errorToast &&
|
||||
toast({
|
||||
title: t(getErrText(err, errorToast)),
|
||||
status: 'error'
|
||||
});
|
||||
|
||||
if (errorToast !== undefined) {
|
||||
const errText = t(getErrText(err, errorToast || ''));
|
||||
if (errText) {
|
||||
toast({
|
||||
title: errText,
|
||||
status: 'error'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -13,7 +13,6 @@ import type {
|
||||
import { InitDateResponse } from '@/global/common/api/systemRes';
|
||||
import { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types';
|
||||
import { SubPlanType } from '@fastgpt/global/support/wallet/sub/type';
|
||||
import { AppSimpleEditConfigTemplateType } from '@fastgpt/global/core/app/type';
|
||||
|
||||
type LoginStoreType = { provider: `${OAuthEnum}`; lastRoute: string; state: string };
|
||||
|
||||
@@ -33,6 +32,9 @@ type State = {
|
||||
gitStar: number;
|
||||
loadGitStar: () => Promise<void>;
|
||||
|
||||
isNotSufficientModal: boolean;
|
||||
setIsNotSufficientModal: (val: boolean) => void;
|
||||
|
||||
feConfigs: FastGPTFeConfigsType;
|
||||
subPlans?: SubPlanType;
|
||||
systemVersion: string;
|
||||
@@ -42,7 +44,6 @@ type State = {
|
||||
audioSpeechModelList: AudioSpeechModelType[];
|
||||
reRankModelList: ReRankModelItemType[];
|
||||
whisperModel?: WhisperModelType;
|
||||
simpleModeTemplates: AppSimpleEditConfigTemplateType[];
|
||||
initStaticData: (e: InitDateResponse) => void;
|
||||
};
|
||||
|
||||
@@ -101,6 +102,13 @@ export const useSystemStore = create<State>()(
|
||||
} catch (error) {}
|
||||
},
|
||||
|
||||
isNotSufficientModal: false,
|
||||
setIsNotSufficientModal(val: boolean) {
|
||||
set((state) => {
|
||||
state.isNotSufficientModal = val;
|
||||
});
|
||||
},
|
||||
|
||||
feConfigs: {},
|
||||
subPlans: undefined,
|
||||
systemVersion: '0.0.0',
|
||||
@@ -110,7 +118,6 @@ export const useSystemStore = create<State>()(
|
||||
audioSpeechModelList: [],
|
||||
reRankModelList: [],
|
||||
whisperModel: undefined,
|
||||
simpleModeTemplates: [],
|
||||
initStaticData(res) {
|
||||
set((state) => {
|
||||
state.feConfigs = res.feConfigs || {};
|
||||
@@ -123,8 +130,6 @@ export const useSystemStore = create<State>()(
|
||||
state.audioSpeechModelList = res.audioSpeechModels ?? state.audioSpeechModelList;
|
||||
state.reRankModelList = res.reRankModels ?? state.reRankModelList;
|
||||
state.whisperModel = res.whisperModel;
|
||||
|
||||
state.simpleModeTemplates = res.simpleModeTemplates;
|
||||
});
|
||||
}
|
||||
})),
|
||||
|
@@ -10,8 +10,8 @@ export const appTemplates: (AppItemType & {
|
||||
{
|
||||
id: 'simpleChat',
|
||||
avatar: '/imgs/module/AI.png',
|
||||
name: 'core.app.template.Simple chat',
|
||||
intro: 'core.app.template.Simple chat desc',
|
||||
name: '简易模板',
|
||||
intro: '一个极其简单的 AI 应用,你可以绑定知识库或工具。',
|
||||
type: AppTypeEnum.simple,
|
||||
modules: [
|
||||
{
|
||||
@@ -290,457 +290,11 @@ export const appTemplates: (AppItemType & {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'simpleDatasetChat',
|
||||
avatar: '/imgs/module/db.png',
|
||||
name: 'core.app.template.Dataset and guide',
|
||||
intro: 'core.app.template.Dataset and guide desc',
|
||||
type: AppTypeEnum.simple,
|
||||
modules: [
|
||||
{
|
||||
moduleId: 'userGuide',
|
||||
name: 'core.module.template.User guide',
|
||||
flowType: 'userGuide',
|
||||
position: {
|
||||
x: 447.98520778293346,
|
||||
y: 721.4016845336229
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'welcomeText',
|
||||
type: 'hidden',
|
||||
valueType: 'string',
|
||||
label: 'core.app.Welcome Text',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: '你好,我是知识库助手,请不要忘记选择知识库噢~\n[你是谁]\n[如何使用]',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'variables',
|
||||
type: 'hidden',
|
||||
valueType: 'any',
|
||||
label: 'core.module.Variable',
|
||||
value: [],
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'questionGuide',
|
||||
valueType: 'boolean',
|
||||
type: 'switch',
|
||||
label: '',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'tts',
|
||||
type: 'hidden',
|
||||
valueType: 'any',
|
||||
label: '',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: {
|
||||
type: 'web'
|
||||
},
|
||||
connected: false
|
||||
}
|
||||
],
|
||||
outputs: []
|
||||
},
|
||||
{
|
||||
moduleId: 'userChatInput',
|
||||
name: 'core.module.template.Chat entrance',
|
||||
flowType: 'questionInput',
|
||||
position: {
|
||||
x: 324.81436595478294,
|
||||
y: 1527.0012457753612
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: 'systemInput',
|
||||
valueType: 'string',
|
||||
label: 'core.module.input.label.user question',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
label: 'core.module.input.label.user question',
|
||||
type: 'source',
|
||||
valueType: 'string',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'datasetSearch',
|
||||
key: 'userChatInput'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'datasetSearch',
|
||||
name: 'core.module.template.Dataset search',
|
||||
flowType: 'datasetSearchNode',
|
||||
showStatus: true,
|
||||
position: {
|
||||
x: 1351.5043753345153,
|
||||
y: 947.0780385418003
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'switch',
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.switch',
|
||||
description: 'core.module.input.description.Trigger',
|
||||
valueType: 'any',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'datasets',
|
||||
type: 'selectDataset',
|
||||
label: 'core.module.input.label.Select dataset',
|
||||
value: [],
|
||||
valueType: 'selectDataset',
|
||||
list: [],
|
||||
required: true,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'similarity',
|
||||
type: 'selectDatasetParamsModal',
|
||||
label: '',
|
||||
value: 0.4,
|
||||
valueType: 'number',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'limit',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
value: 1500,
|
||||
valueType: 'number',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'searchMode',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: 'embedding',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'usingReRank',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'boolean',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'datasetSearchUsingExtensionQuery',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'boolean',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'datasetSearchExtensionModel',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: 'gpt-3.5-turbo',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'datasetSearchExtensionBg',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: '',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: 'custom',
|
||||
label: '',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'isEmpty',
|
||||
label: 'core.module.output.label.Search result empty',
|
||||
type: 'source',
|
||||
valueType: 'boolean',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'unEmpty',
|
||||
label: 'core.module.output.label.Search result not empty',
|
||||
type: 'source',
|
||||
valueType: 'boolean',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'quoteQA',
|
||||
label: 'core.module.Dataset quote.label',
|
||||
type: 'source',
|
||||
valueType: 'datasetQuote',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'quoteQA'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'finish',
|
||||
label: 'core.module.output.label.running done',
|
||||
description: 'core.module.output.description.running done',
|
||||
valueType: 'boolean',
|
||||
type: 'source',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
label: 'core.module.input.label.user question',
|
||||
type: 'hidden',
|
||||
valueType: 'string',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'userChatInput'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
name: 'AI 对话',
|
||||
flowType: 'chatNode',
|
||||
showStatus: true,
|
||||
position: {
|
||||
x: 2022.7264786978908,
|
||||
y: 1006.3102431257475
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'switch',
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.switch',
|
||||
description: 'core.module.input.description.Trigger',
|
||||
valueType: 'any',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'model',
|
||||
type: 'selectLLMModel',
|
||||
label: 'core.module.input.label.aiModel',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: 'gpt-3.5-turbo',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'temperature',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
value: 0,
|
||||
valueType: 'number',
|
||||
min: 0,
|
||||
max: 10,
|
||||
step: 1,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'maxToken',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
value: 2000,
|
||||
valueType: 'number',
|
||||
min: 100,
|
||||
max: 4000,
|
||||
step: 50,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
markList: [
|
||||
{
|
||||
label: '100',
|
||||
value: 100
|
||||
},
|
||||
{
|
||||
label: '4000',
|
||||
value: 4000
|
||||
}
|
||||
],
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'isResponseAnswerText',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
value: true,
|
||||
valueType: 'boolean',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quoteTemplate',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: '',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quotePrompt',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: '',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'aiSettings',
|
||||
type: 'aiSettings',
|
||||
label: '',
|
||||
valueType: 'any',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'systemPrompt',
|
||||
type: 'textarea',
|
||||
label: 'core.ai.Prompt',
|
||||
max: 300,
|
||||
valueType: 'string',
|
||||
description: 'core.app.tip.chatNodeSystemPromptTip',
|
||||
placeholder: 'core.app.tip.chatNodeSystemPromptTip',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
value: '',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'numberInput',
|
||||
label: 'core.module.input.label.chat history',
|
||||
required: true,
|
||||
min: 0,
|
||||
max: 30,
|
||||
valueType: 'chatHistory',
|
||||
value: 6,
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: 'custom',
|
||||
label: '',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'quoteQA',
|
||||
type: 'target',
|
||||
label: '知识库引用',
|
||||
description: 'core.module.Dataset quote.Input description',
|
||||
valueType: 'datasetQuote',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'answerText',
|
||||
label: 'core.module.output.label.Ai response content',
|
||||
description: 'core.module.output.description.Ai response content',
|
||||
valueType: 'string',
|
||||
type: 'source',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'finish',
|
||||
label: 'core.module.output.label.running done',
|
||||
description: 'core.module.output.description.running done',
|
||||
valueType: 'boolean',
|
||||
type: 'source',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
label: 'core.module.output.label.New context',
|
||||
description: 'core.module.output.description.New context',
|
||||
valueType: 'chatHistory',
|
||||
type: 'source',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
label: 'core.module.input.label.user question',
|
||||
type: 'hidden',
|
||||
valueType: 'string',
|
||||
targets: []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'chatGuide',
|
||||
avatar: '/imgs/module/userGuide.png',
|
||||
name: 'core.app.template.Guide and variables',
|
||||
intro: 'core.app.template.Guide and variables desc',
|
||||
name: '对话引导 + 变量',
|
||||
intro: '可以在对话开始发送一段提示,或者让用户填写一些内容,作为本次对话的变量',
|
||||
type: AppTypeEnum.simple,
|
||||
modules: [
|
||||
{
|
||||
@@ -1052,11 +606,444 @@ export const appTemplates: (AppItemType & {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'simpleDatasetChat',
|
||||
avatar: '/imgs/module/db.png',
|
||||
name: '知识库+对话引导',
|
||||
intro: '每次提问时进行一次知识库搜索,将搜索结果注入 LLM 模型进行参考回答',
|
||||
type: AppTypeEnum.advanced,
|
||||
modules: [
|
||||
{
|
||||
moduleId: 'userGuide',
|
||||
name: 'core.module.template.User guide',
|
||||
intro: 'core.app.tip.userGuideTip',
|
||||
avatar: '/imgs/module/userGuide.png',
|
||||
flowType: 'userGuide',
|
||||
position: {
|
||||
x: 447.98520778293346,
|
||||
y: 721.4016845336229
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'welcomeText',
|
||||
type: 'hidden',
|
||||
valueType: 'string',
|
||||
label: 'core.app.Welcome Text',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: '你好,我是知识库助手,请不要忘记选择知识库噢~\n[你是谁]\n[如何使用]',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'variables',
|
||||
type: 'hidden',
|
||||
valueType: 'any',
|
||||
label: 'core.module.Variable',
|
||||
value: [],
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'questionGuide',
|
||||
valueType: 'boolean',
|
||||
type: 'switch',
|
||||
label: '',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'tts',
|
||||
type: 'hidden',
|
||||
valueType: 'any',
|
||||
label: '',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: {
|
||||
type: 'web'
|
||||
},
|
||||
connected: false
|
||||
}
|
||||
],
|
||||
outputs: []
|
||||
},
|
||||
{
|
||||
moduleId: 'userChatInput',
|
||||
name: 'core.module.template.Chat entrance',
|
||||
intro: '当用户发送一个内容后,流程将会从这个模块开始执行。',
|
||||
avatar: '/imgs/module/userChatInput.svg',
|
||||
flowType: 'questionInput',
|
||||
position: {
|
||||
x: 324.81436595478294,
|
||||
y: 1527.0012457753612
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: 'systemInput',
|
||||
valueType: 'string',
|
||||
label: 'core.module.input.label.user question',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
label: 'core.module.input.label.user question',
|
||||
type: 'source',
|
||||
valueType: 'string',
|
||||
targets: [
|
||||
{
|
||||
moduleId: '0voh5n',
|
||||
key: 'userChatInput'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: '63toub',
|
||||
name: 'AI 对话',
|
||||
intro: 'AI 大模型对话',
|
||||
avatar: '/imgs/module/AI.png',
|
||||
flowType: 'chatNode',
|
||||
showStatus: true,
|
||||
position: {
|
||||
x: 1962.4010270586014,
|
||||
y: 1026.9105717680477
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'switch',
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.switch',
|
||||
description: 'core.module.input.description.Trigger',
|
||||
valueType: 'any',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'model',
|
||||
type: 'settingLLMModel',
|
||||
label: 'core.module.input.label.aiModel',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: 'gpt-3.5-turbo',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'temperature',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
value: 0,
|
||||
valueType: 'number',
|
||||
min: 0,
|
||||
max: 10,
|
||||
step: 1,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'maxToken',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
value: 2000,
|
||||
valueType: 'number',
|
||||
min: 100,
|
||||
max: 4000,
|
||||
step: 50,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'isResponseAnswerText',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
value: true,
|
||||
valueType: 'boolean',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quoteTemplate',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quotePrompt',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'systemPrompt',
|
||||
type: 'textarea',
|
||||
max: 3000,
|
||||
valueType: 'string',
|
||||
label: 'core.ai.Prompt',
|
||||
description: 'core.app.tip.chatNodeSystemPromptTip',
|
||||
placeholder: 'core.app.tip.chatNodeSystemPromptTip',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'numberInput',
|
||||
label: 'core.module.input.label.chat history',
|
||||
required: true,
|
||||
min: 0,
|
||||
max: 30,
|
||||
valueType: 'chatHistory',
|
||||
value: 6,
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: 'custom',
|
||||
label: '',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
toolDescription: '用户问题',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'quoteQA',
|
||||
type: 'settingDatasetQuotePrompt',
|
||||
label: '知识库引用',
|
||||
description: 'core.module.Dataset quote.Input description',
|
||||
valueType: 'datasetQuote',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
label: 'core.module.input.label.user question',
|
||||
type: 'hidden',
|
||||
valueType: 'string',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
label: 'core.module.output.label.New context',
|
||||
description: 'core.module.output.description.New context',
|
||||
valueType: 'chatHistory',
|
||||
type: 'source',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'answerText',
|
||||
label: 'core.module.output.label.Ai response content',
|
||||
description: 'core.module.output.description.Ai response content',
|
||||
valueType: 'string',
|
||||
type: 'source',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'finish',
|
||||
label: 'core.module.output.label.running done',
|
||||
description: 'core.module.output.description.running done',
|
||||
valueType: 'boolean',
|
||||
type: 'source',
|
||||
targets: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: '0voh5n',
|
||||
name: '知识库搜索',
|
||||
intro: '调用知识库搜索能力,查找“有可能”与问题相关的内容',
|
||||
avatar: '/imgs/module/db.png',
|
||||
flowType: 'datasetSearchNode',
|
||||
showStatus: true,
|
||||
position: {
|
||||
x: 1098.245668870126,
|
||||
y: 1166.7285333032098
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'switch',
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.switch',
|
||||
description: 'core.module.input.description.Trigger',
|
||||
valueType: 'any',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'datasets',
|
||||
type: 'selectDataset',
|
||||
label: 'core.module.input.label.Select dataset',
|
||||
value: [],
|
||||
valueType: 'selectDataset',
|
||||
list: [],
|
||||
required: true,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'similarity',
|
||||
type: 'selectDatasetParamsModal',
|
||||
label: '',
|
||||
value: 0.4,
|
||||
valueType: 'number',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'limit',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
value: 1500,
|
||||
valueType: 'number',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'searchMode',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: 'embedding',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'usingReRank',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'boolean',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'datasetSearchUsingExtensionQuery',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'boolean',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'datasetSearchExtensionModel',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'datasetSearchExtensionBg',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: '',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: 'custom',
|
||||
label: '',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
toolDescription: '需要检索的内容',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
label: 'core.module.input.label.user question',
|
||||
type: 'hidden',
|
||||
valueType: 'string',
|
||||
targets: [
|
||||
{
|
||||
moduleId: '63toub',
|
||||
key: 'userChatInput'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'isEmpty',
|
||||
label: 'core.module.output.label.Search result empty',
|
||||
type: 'source',
|
||||
valueType: 'boolean',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'unEmpty',
|
||||
label: 'core.module.output.label.Search result not empty',
|
||||
type: 'source',
|
||||
valueType: 'boolean',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'quoteQA',
|
||||
label: 'core.module.Dataset quote.label',
|
||||
type: 'source',
|
||||
valueType: 'datasetQuote',
|
||||
targets: [
|
||||
{
|
||||
moduleId: '63toub',
|
||||
key: 'quoteQA'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'finish',
|
||||
label: 'core.module.output.label.running done',
|
||||
description: 'core.module.output.description.running done',
|
||||
valueType: 'boolean',
|
||||
type: 'source',
|
||||
targets: []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'CQ',
|
||||
avatar: '/imgs/module/cq.png',
|
||||
name: 'core.app.template.Classify and dataset',
|
||||
intro: 'core.app.template.Classify and dataset desc',
|
||||
name: '问题分类 + 知识库',
|
||||
intro: '先对用户的问题进行分类,再根据不同类型问题,执行不同的操作',
|
||||
type: AppTypeEnum.advanced,
|
||||
modules: [
|
||||
{
|
||||
@@ -1408,15 +1395,6 @@ export const appTemplates: (AppItemType & {
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'aiSettings',
|
||||
type: 'aiSettings',
|
||||
label: '',
|
||||
valueType: 'any',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'systemPrompt',
|
||||
type: 'textarea',
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import { AppSimpleEditFormType } from '@fastgpt/global/core/app/type';
|
||||
import { ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
import { POST } from '@/web/common/api/request';
|
||||
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';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { ModuleIOValueTypeEnum, ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { UserInputModule } from '@fastgpt/global/core/module/template/system/userInput';
|
||||
import { ToolModule } from '@fastgpt/global/core/module/template/system/tools';
|
||||
import { DatasetSearchModule } from '@fastgpt/global/core/module/template/system/datasetSearch';
|
||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
|
||||
export async function postForm2Modules(data: AppSimpleEditFormType) {
|
||||
const llmModelList = useSystemStore.getState().llmModelList;
|
||||
function userGuideTemplate(formData: AppSimpleEditFormType): ModuleItemType[] {
|
||||
return [
|
||||
{
|
||||
@@ -48,16 +48,569 @@ export async function postForm2Modules(data: AppSimpleEditFormType) {
|
||||
}
|
||||
];
|
||||
}
|
||||
const maxToken =
|
||||
llmModelList.find((item) => item.model === data.aiSettings.model)?.maxResponse || 4000;
|
||||
function simpleChatTemplate(formData: AppSimpleEditFormType): ModuleItemType[] {
|
||||
return [
|
||||
{
|
||||
moduleId: 'userChatInput',
|
||||
name: 'core.module.template.Chat entrance',
|
||||
avatar: '/imgs/module/userChatInput.png',
|
||||
flowType: 'questionInput',
|
||||
position: {
|
||||
x: 464.32198615344566,
|
||||
y: 1602.2698463081606
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: 'systemInput',
|
||||
valueType: 'string',
|
||||
label: 'core.module.input.label.user question',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
label: 'core.module.input.label.user question',
|
||||
type: 'source',
|
||||
valueType: 'string',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'userChatInput'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
name: 'AI 对话',
|
||||
avatar: '/imgs/module/AI.png',
|
||||
flowType: 'chatNode',
|
||||
showStatus: true,
|
||||
position: {
|
||||
x: 981.9682828103937,
|
||||
y: 890.014595014464
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'switch',
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.switch',
|
||||
valueType: 'any',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'model',
|
||||
type: 'selectLLMModel',
|
||||
label: 'core.module.input.label.aiModel',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: formData.aiSettings.model,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'temperature',
|
||||
type: 'hidden',
|
||||
label: '温度',
|
||||
value: formData.aiSettings.temperature,
|
||||
valueType: 'number',
|
||||
min: 0,
|
||||
max: 10,
|
||||
step: 1,
|
||||
markList: [
|
||||
{
|
||||
label: '严谨',
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: '发散',
|
||||
value: 10
|
||||
}
|
||||
],
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'maxToken',
|
||||
type: 'hidden',
|
||||
label: '回复上限',
|
||||
value: formData.aiSettings.maxToken,
|
||||
valueType: 'number',
|
||||
min: 100,
|
||||
max: 4000,
|
||||
step: 50,
|
||||
markList: [
|
||||
{
|
||||
label: '100',
|
||||
value: 100
|
||||
},
|
||||
{
|
||||
label: '4000',
|
||||
value: 4000
|
||||
}
|
||||
],
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'isResponseAnswerText',
|
||||
type: 'hidden',
|
||||
label: '返回AI内容',
|
||||
value: true,
|
||||
valueType: 'boolean',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quoteTemplate',
|
||||
type: 'hidden',
|
||||
label: '引用内容模板',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: '',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quotePrompt',
|
||||
type: 'hidden',
|
||||
label: '引用内容提示词',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: '',
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'aiSettings',
|
||||
type: 'aiSettings',
|
||||
label: '',
|
||||
valueType: 'any',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'systemPrompt',
|
||||
type: 'textarea',
|
||||
label: 'core.ai.Prompt',
|
||||
max: 300,
|
||||
valueType: 'string',
|
||||
description:
|
||||
'模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}',
|
||||
placeholder:
|
||||
'模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
value: formData.aiSettings.systemPrompt,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'numberInput',
|
||||
label: 'core.module.input.label.chat history',
|
||||
required: true,
|
||||
min: 0,
|
||||
max: 30,
|
||||
valueType: 'chatHistory',
|
||||
value: formData.aiSettings.maxHistories,
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quoteQA',
|
||||
type: 'target',
|
||||
label: '引用内容',
|
||||
description: "对象数组格式,结构:\n [{q:'问题',a:'回答'}]",
|
||||
valueType: 'datasetQuote',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.user question',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'answerText',
|
||||
label: 'AI回复',
|
||||
description: '将在 stream 回复完毕后触发',
|
||||
valueType: 'string',
|
||||
type: 'source',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'finish',
|
||||
label: 'core.module.output.label.running done',
|
||||
description: 'core.module.output.description.running done',
|
||||
valueType: 'boolean',
|
||||
type: 'source',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
label: '新的上下文',
|
||||
description: '将本次回复内容拼接上历史记录,作为新的上下文返回',
|
||||
valueType: 'chatHistory',
|
||||
type: 'source',
|
||||
targets: []
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
function toolTemplates(formData: AppSimpleEditFormType): ModuleItemType[] {
|
||||
let tools: ModuleItemType[] =
|
||||
formData.dataset.datasets.length > 0
|
||||
? [
|
||||
{
|
||||
moduleId: getNanoid(6),
|
||||
name: DatasetSearchModule.name,
|
||||
intro: DatasetSearchModule.intro,
|
||||
avatar: DatasetSearchModule.avatar,
|
||||
flowType: DatasetSearchModule.flowType,
|
||||
showStatus: DatasetSearchModule.showStatus,
|
||||
position: {
|
||||
x: 1000,
|
||||
y: 2143
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'switch',
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.switch',
|
||||
description: 'core.module.input.description.Trigger',
|
||||
valueType: 'any',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'datasets',
|
||||
type: 'selectDataset',
|
||||
label: '关联的知识库',
|
||||
value: formData.dataset.datasets,
|
||||
valueType: 'selectDataset',
|
||||
required: true,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'similarity',
|
||||
type: 'selectDatasetParamsModal',
|
||||
label: '',
|
||||
value: formData.dataset.similarity,
|
||||
valueType: 'number',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'limit',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
value: formData.dataset.limit,
|
||||
valueType: 'number',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'searchMode',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: formData.dataset.searchMode,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'usingReRank',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'boolean',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: formData.dataset.usingReRank,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'datasetSearchUsingExtensionQuery',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'boolean',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: formData.dataset.datasetSearchUsingExtensionQuery,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'datasetSearchExtensionModel',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
connected: false,
|
||||
value: formData.dataset.datasetSearchExtensionModel
|
||||
},
|
||||
{
|
||||
key: 'datasetSearchExtensionBg',
|
||||
type: 'hidden',
|
||||
label: '',
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
value: formData.dataset.datasetSearchExtensionBg,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: 'custom',
|
||||
label: '',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
toolDescription: '需要检索的内容',
|
||||
connected: false
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
label: 'core.module.input.label.user question',
|
||||
type: 'hidden',
|
||||
valueType: 'string',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'isEmpty',
|
||||
label: 'core.module.output.label.Search result empty',
|
||||
type: 'source',
|
||||
valueType: 'boolean',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'unEmpty',
|
||||
label: 'core.module.output.label.Search result not empty',
|
||||
type: 'source',
|
||||
valueType: 'boolean',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'quoteQA',
|
||||
label: 'core.module.Dataset quote.label',
|
||||
type: 'source',
|
||||
valueType: 'datasetQuote',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'finish',
|
||||
label: 'core.module.output.label.running done',
|
||||
description: 'core.module.output.description.running done',
|
||||
valueType: 'boolean',
|
||||
type: 'source',
|
||||
targets: []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
: [];
|
||||
|
||||
const props: FormatForm2ModulesProps = {
|
||||
formData: data,
|
||||
chatModelMaxToken: maxToken,
|
||||
llmModelList
|
||||
};
|
||||
tools = tools.concat(
|
||||
formData.selectedTools.map((tool, i) => ({
|
||||
moduleId: getNanoid(6),
|
||||
name: tool.name,
|
||||
intro: tool.intro,
|
||||
avatar: tool.avatar,
|
||||
flowType: tool.flowType,
|
||||
showStatus: tool.showStatus,
|
||||
position: {
|
||||
x: 1000 + (300 * i + 1),
|
||||
y: 2143
|
||||
},
|
||||
inputs: tool.inputs,
|
||||
outputs: tool.outputs
|
||||
}))
|
||||
);
|
||||
const modules: ModuleItemType[] = [
|
||||
{
|
||||
moduleId: 'userChatInput',
|
||||
name: UserInputModule.name,
|
||||
intro: UserInputModule.intro,
|
||||
avatar: UserInputModule.avatar,
|
||||
flowType: UserInputModule.flowType,
|
||||
position: {
|
||||
x: 324.81436595478294,
|
||||
y: 1527.0012457753612
|
||||
},
|
||||
inputs: UserInputModule.inputs,
|
||||
outputs: [
|
||||
{
|
||||
...UserInputModule.outputs[0],
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'yt7o6j',
|
||||
key: 'userChatInput'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'yt7o6j',
|
||||
name: ToolModule.name,
|
||||
intro: ToolModule.intro,
|
||||
avatar: ToolModule.avatar,
|
||||
flowType: ToolModule.flowType,
|
||||
showStatus: ToolModule.showStatus,
|
||||
position: {
|
||||
x: 890.8756545707358,
|
||||
y: 1078.2777133587558
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'switch',
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.switch',
|
||||
description: 'core.module.input.description.Trigger',
|
||||
valueType: 'any',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'model',
|
||||
type: 'selectLLMModel',
|
||||
label: 'core.module.input.label.aiModel',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false,
|
||||
llmModelType: 'toolCall',
|
||||
value: formData.aiSettings.model,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: ModuleInputKeyEnum.aiChatTemperature,
|
||||
type: FlowNodeInputTypeEnum.hidden, // Set in the pop-up window
|
||||
label: '',
|
||||
value: formData.aiSettings.temperature,
|
||||
valueType: ModuleIOValueTypeEnum.number,
|
||||
min: 0,
|
||||
max: 10,
|
||||
step: 1,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false
|
||||
},
|
||||
{
|
||||
key: ModuleInputKeyEnum.aiChatMaxToken,
|
||||
type: FlowNodeInputTypeEnum.hidden, // Set in the pop-up window
|
||||
label: '',
|
||||
value: formData.aiSettings.maxToken,
|
||||
valueType: ModuleIOValueTypeEnum.number,
|
||||
min: 100,
|
||||
max: 4000,
|
||||
step: 50,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false
|
||||
},
|
||||
{
|
||||
key: 'systemPrompt',
|
||||
type: 'textarea',
|
||||
max: 3000,
|
||||
valueType: 'string',
|
||||
label: 'core.ai.Prompt',
|
||||
description: 'core.app.tip.chatNodeSystemPromptTip',
|
||||
placeholder: 'core.app.tip.chatNodeSystemPromptTip',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false,
|
||||
value: formData.aiSettings.systemPrompt
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'numberInput',
|
||||
label: 'core.module.input.label.chat history',
|
||||
required: true,
|
||||
min: 0,
|
||||
max: 30,
|
||||
valueType: 'chatHistory',
|
||||
value: formData.aiSettings.maxHistories,
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: 'custom',
|
||||
label: '',
|
||||
required: true,
|
||||
valueType: 'string',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true,
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
label: 'core.module.input.label.user question',
|
||||
type: 'hidden',
|
||||
valueType: 'string',
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'selectedTools',
|
||||
valueType: 'tools',
|
||||
type: 'hidden',
|
||||
targets: tools.map((tool) => ({
|
||||
moduleId: tool.moduleId,
|
||||
key: 'selectedTools'
|
||||
}))
|
||||
},
|
||||
{
|
||||
key: 'finish',
|
||||
label: 'core.module.output.label.running done',
|
||||
description: 'core.module.output.description.running done',
|
||||
valueType: 'boolean',
|
||||
type: 'source',
|
||||
targets: []
|
||||
}
|
||||
]
|
||||
},
|
||||
...tools
|
||||
];
|
||||
|
||||
const modules = await POST<ModuleItemType[]>(`/core/app/form2Modules/fastgpt-universal`, props);
|
||||
return modules;
|
||||
}
|
||||
const modules =
|
||||
data.dataset.datasets.length > 0 || data.selectedTools.length > 0
|
||||
? toolTemplates(data)
|
||||
: simpleChatTemplate(data);
|
||||
|
||||
return [...userGuideTemplate(data), ...modules];
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import ParentPaths from '@/components/common/ParentPaths';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { getDatasetCollectionPathById, getDatasetCollections } from '@/web/core/dataset/api';
|
||||
|
@@ -1,5 +1,7 @@
|
||||
import { GET, POST, DELETE, PUT } from '@/web/common/api/request';
|
||||
import { FlowModuleTemplateType } from '@fastgpt/global/core/module/type';
|
||||
import { FlowNodeTemplateType } from '@fastgpt/global/core/module/type';
|
||||
import { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
|
||||
import { PluginTypeEnum } from '@fastgpt/global/core/plugin/constants';
|
||||
import {
|
||||
CreateOnePluginParams,
|
||||
PluginListItemType,
|
||||
@@ -10,9 +12,24 @@ import { PluginItemSchema } from '@fastgpt/global/core/plugin/type';
|
||||
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 getPlugTemplates = () => GET<FlowModuleTemplateType[]>('/core/plugin/templates');
|
||||
export const getPluginPaths = (parentId?: string) =>
|
||||
GET<ParentTreePathItemType[]>('/core/plugin/paths', { parentId });
|
||||
|
||||
// http plugin
|
||||
export const getApiSchemaByUrl = (url: string) =>
|
||||
POST<Object>('/core/plugin/httpPlugin/getApiSchemaByUrl', { url });
|
||||
|
||||
/* work flow */
|
||||
export const getPlugTemplates = () => GET<FlowNodeTemplateType[]>('/core/plugin/templates');
|
||||
export const getUserPlugins = (data: { parentId?: string; type?: `${PluginTypeEnum}` }) =>
|
||||
GET<PluginListItemType[]>('/core/plugin/list', data);
|
||||
|
||||
export const getTeamPlugTemplates = (data: { parentId?: string | null; searchKey?: string }) =>
|
||||
GET<FlowNodeTemplateType[]>('/core/plugin/pluginTemplate/getTeamPluginTemplates', data);
|
||||
export const getSystemPlugTemplates = () =>
|
||||
GET<FlowNodeTemplateType[]>('/core/plugin/pluginTemplate/getSystemPluginTemplates');
|
||||
|
||||
export const getPreviewPluginModule = (id: string) =>
|
||||
GET<FlowModuleTemplateType>('/core/plugin/getPreviewModule', { id });
|
||||
GET<FlowNodeTemplateType>('/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 });
|
||||
export const delOnePlugin = (pluginId: string) => DELETE('/core/plugin/delete', { pluginId });
|
||||
|
@@ -1,28 +0,0 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { getPlugTemplates } from '../api';
|
||||
import { FlowModuleTemplateType } from '@fastgpt/global/core/module/type';
|
||||
|
||||
type State = {
|
||||
pluginModuleTemplates: FlowModuleTemplateType[];
|
||||
loadPluginTemplates: (init?: boolean) => Promise<FlowModuleTemplateType[]>;
|
||||
};
|
||||
|
||||
export const usePluginStore = create<State>()(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
pluginModuleTemplates: [],
|
||||
async loadPluginTemplates(init) {
|
||||
if (!init && get().pluginModuleTemplates.length > 0) {
|
||||
return get().pluginModuleTemplates;
|
||||
}
|
||||
const templates = await getPlugTemplates();
|
||||
set((state) => {
|
||||
state.pluginModuleTemplates = templates;
|
||||
});
|
||||
return templates;
|
||||
}
|
||||
}))
|
||||
)
|
||||
);
|
64
projects/app/src/web/core/workflow/store/workflow.ts
Normal file
64
projects/app/src/web/core/workflow/store/workflow.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { FlowNodeTemplateType } from '@fastgpt/global/core/module/type';
|
||||
import { getTeamPlugTemplates, getSystemPlugTemplates } from '../../plugin/api';
|
||||
|
||||
type State = {
|
||||
basicNodeTemplates: FlowNodeTemplateType[];
|
||||
setBasicNodeTemplates: (basicNodeTemplates: FlowNodeTemplateType[]) => void;
|
||||
systemNodeTemplates: FlowNodeTemplateType[];
|
||||
loadSystemNodeTemplates: (init?: boolean) => Promise<FlowNodeTemplateType[]>;
|
||||
teamPluginNodeTemplates: FlowNodeTemplateType[];
|
||||
loadTeamPluginNodeTemplates: (e?: {
|
||||
parentId?: string | null;
|
||||
searchKey?: string;
|
||||
init?: boolean;
|
||||
}) => Promise<FlowNodeTemplateType[]>;
|
||||
};
|
||||
|
||||
export const useWorkflowStore = create<State>()(
|
||||
devtools(
|
||||
persist(
|
||||
immer((set, get) => ({
|
||||
basicNodeTemplates: [],
|
||||
setBasicNodeTemplates: (basicNodeTemplates) => {
|
||||
set((state) => {
|
||||
state.basicNodeTemplates = basicNodeTemplates;
|
||||
});
|
||||
},
|
||||
systemNodeTemplates: [],
|
||||
async loadSystemNodeTemplates(init) {
|
||||
if (!init && get().systemNodeTemplates.length > 0) {
|
||||
return get().systemNodeTemplates;
|
||||
}
|
||||
const templates = await getSystemPlugTemplates();
|
||||
set((state) => {
|
||||
state.systemNodeTemplates = templates;
|
||||
});
|
||||
return templates;
|
||||
},
|
||||
teamPluginNodeTemplates: [],
|
||||
async loadTeamPluginNodeTemplates(e) {
|
||||
const { parentId = null, searchKey, init } = e || {};
|
||||
|
||||
if (!init && get().teamPluginNodeTemplates.length > 0) {
|
||||
return get().teamPluginNodeTemplates;
|
||||
}
|
||||
const templates = await getTeamPlugTemplates({
|
||||
parentId: parentId || null,
|
||||
searchKey: searchKey
|
||||
});
|
||||
set((state) => {
|
||||
state.teamPluginNodeTemplates = templates;
|
||||
});
|
||||
return templates;
|
||||
}
|
||||
})),
|
||||
{
|
||||
name: 'datasetStore',
|
||||
partialize: (state) => ({})
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
@@ -46,16 +46,12 @@ svg {
|
||||
|
||||
div {
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: transparent !important;
|
||||
background: rgba(189, 193, 197, 0.7) !important;
|
||||
transition: background 1s;
|
||||
}
|
||||
&:hover {
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: rgba(189, 193, 197, 0.7) !important;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(189, 193, 197, 1) !important;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(189, 193, 197, 1) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user