Optimize the project structure and introduce DDD design (#394)

This commit is contained in:
Archer
2023-10-12 17:46:37 +08:00
committed by GitHub
parent 76ac5238b6
commit ad7a17bf40
193 changed files with 1169 additions and 1084 deletions

View File

@@ -242,7 +242,7 @@
"openapi": {
"app key tips": "These keys have the identification of the current application and can be used by external access.",
"key alias": "Alias of key, for display only",
"key tips": "You can use API keys to access certain interfaces"
"key tips": "You can use the API Key to access certain interfaces (you can't access the application, you need to use the API key within the application to access the application)."
},
"outlink": {
"Copy Iframe": "Copy Iframe",

View File

@@ -242,7 +242,7 @@
"openapi": {
"app key tips": "这些 key 已有当前应用标识,具体使用可参考文档",
"key alias": "key 的别名,仅用于展示",
"key tips": "你可以使用 API 秘钥访问一些特定的接口"
"key tips": "你可以使用 API 秘钥访问一些特定的接口(无法访问应用访问应用需使用应用内的API Key)"
},
"outlink": {
"Copy Iframe": "嵌入网页",

View File

@@ -1,5 +0,0 @@
import { GET, POST, PUT, DELETE } from '@/api/request';
import { CreateTrainingBillType } from './index.d';
export const postCreateTrainingBill = (data: CreateTrainingBillType) =>
POST<string>(`/common/bill/createTrainingBill`, data);

View File

@@ -1,5 +0,0 @@
import { GET, POST, PUT, DELETE } from '@/api/request';
import { CreateQuestionGuideProps } from './type';
export const postQuestionGuide = (data: CreateQuestionGuideProps, cancelToken: AbortController) =>
POST<string[]>('/core/ai/agent/createQuestionGuide', data, { cancelToken });

View File

@@ -1,28 +0,0 @@
import { KbTypeEnum } from '@/constants/dataset';
import type { RequestPaging } from '@/types';
import { TrainingModeEnum } from '@/constants/plugin';
import { DatasetDataItemType } from '@/types/core/dataset/data';
export type PushDataProps = {
kbId: string;
data: DatasetDataItemType[];
mode: `${TrainingModeEnum}`;
prompt?: string;
billId?: string;
};
export type PushDataResponse = {
insertLen: number;
};
export type UpdateDataPrams = {
dataId: string;
kbId: string;
a?: string;
q?: string;
};
export type GetDatasetDataListProps = RequestPaging & {
kbId: string;
searchText: string;
fileId: string;
};

View File

@@ -1,72 +0,0 @@
import { GET, POST, PUT, DELETE } from '@/api/request';
import type { DatasetDataItemType } from '@/types/core/dataset/data';
import type {
PushDataProps,
PushDataResponse,
UpdateDataPrams,
GetDatasetDataListProps
} from './data.d';
import { QuoteItemType } from '@/types/chat';
import { getToken } from '@/utils/user';
import download from 'downloadjs';
/* kb data */
export const getDatasetDataList = (data: GetDatasetDataListProps) =>
POST(`/core/dataset/data/getDataList`, data);
/**
* export and download data
*/
export const exportDatasetData = (data: { kbId: string }) =>
fetch(`/api/core/dataset/data/exportAll?kbId=${data.kbId}`, {
method: 'GET',
headers: {
token: getToken()
}
})
.then(async (res) => {
if (!res.ok) {
const data = await res.json();
throw new Error(data?.message || 'Export failed');
}
return res.blob();
})
.then((blob) => download(blob, 'dataset.csv', 'text/csv'));
/**
* 获取模型正在拆分数据的数量
*/
export const getTrainingData = (data: { kbId: string; init: boolean }) =>
POST<{
qaListLen: number;
vectorListLen: number;
}>(`/core/dataset/data/getTrainingData`, data);
/* get length of system training queue */
export const getTrainingQueueLen = () => GET<number>(`/core/dataset/data/getQueueLen`);
export const getDatasetDataItemById = (dataId: string) =>
GET<QuoteItemType>(`/core/dataset/data/getDataById`, { dataId });
/**
* push data to training queue
*/
export const postChunks2Dataset = (data: PushDataProps) =>
POST<PushDataResponse>(`/core/dataset/data/pushData`, data);
/**
* insert one data to dataset (immediately insert)
*/
export const postData2Dataset = (data: { kbId: string; data: DatasetDataItemType }) =>
POST<string>(`/core/dataset/data/insertData`, data);
/**
* 更新一条数据
*/
export const putDatasetDataById = (data: UpdateDataPrams) =>
PUT('/core/dataset/data/updateData', data);
/**
* 删除一条知识库数据
*/
export const delOneDatasetDataById = (dataId: string) =>
DELETE(`/core/dataset/data/delDataById?dataId=${dataId}`);

View File

@@ -1,10 +0,0 @@
import { RequestPaging } from '../../../types/index';
export type GetFileListProps = RequestPaging & {
kbId: string;
searchText: string;
};
export type UpdateFileProps = { id: string; name?: string; datasetUsed?: boolean };
export type MarkFileUsedProps = { fileIds: string[] };

View File

@@ -1,19 +0,0 @@
import { GET, POST, PUT, DELETE } from '@/api/request';
import type { DatasetFileItemType } from '@/types/core/dataset/file';
import type { GSFileInfoType } from '@/types/common/file';
import type { GetFileListProps, UpdateFileProps, MarkFileUsedProps } from './file.d';
export const getDatasetFiles = (data: GetFileListProps) =>
POST<DatasetFileItemType[]>(`/core/dataset/file/list`, data);
export const delDatasetFileById = (params: { fileId: string; kbId: string }) =>
DELETE(`/core/dataset/file/delById`, params);
export const getFileInfoById = (fileId: string) =>
GET<GSFileInfoType>(`/core/dataset/file/detail`, { fileId });
export const delDatasetEmptyFiles = (kbId: string) =>
DELETE(`/core/dataset/file/delEmptyFiles`, { kbId });
export const updateDatasetFile = (data: UpdateFileProps) => PUT(`/core/dataset/file/update`, data);
export const putMarkFilesUsed = (data: MarkFileUsedProps) =>
PUT(`/core/dataset/file/markUsed`, data);

View File

@@ -1,34 +0,0 @@
import { KbTypeEnum } from '@/constants/dataset';
import type { RequestPaging } from '@/types';
import { TrainingModeEnum } from '@/constants/plugin';
import type { SearchTestItemType } from '@/types/core/dataset';
export type DatasetUpdateParams = {
id: string;
parentId?: string;
tags?: string;
name?: string;
avatar?: string;
};
export type CreateDatasetParams = {
parentId?: string;
name: string;
tags: string[];
avatar: string;
vectorModel?: string;
type: `${KbTypeEnum}`;
};
export type DatasetUpdateParams = {
id: string;
parentId?: string;
tags?: string;
name?: string;
avatar?: string;
};
export type SearchTestProps = {
kbId: string;
text: string;
};
export type SearchTestResponseType = SearchTestItemType['results'];

View File

@@ -1,32 +0,0 @@
import { GET, POST, PUT, DELETE } from '@/api/request';
import type { DatasetItemType, DatasetsItemType, DatasetPathItemType } from '@/types/core/dataset';
import type {
DatasetUpdateParams,
CreateDatasetParams,
SearchTestProps,
SearchTestResponseType
} from './index.d';
import { KbTypeEnum } from '@/constants/dataset';
export const getDatasets = (data: { parentId?: string; type?: `${KbTypeEnum}` }) =>
GET<DatasetsItemType[]>(`/core/dataset/list`, data);
/**
* get type=dataset list
*/
export const getAllDataset = () => GET<DatasetsItemType[]>(`/core/dataset/allDataset`);
export const getDatasetPaths = (parentId?: string) =>
GET<DatasetPathItemType[]>('/core/dataset/paths', { parentId });
export const getDatasetById = (id: string) => GET<DatasetItemType>(`/core/dataset/detail?id=${id}`);
export const postCreateDataset = (data: CreateDatasetParams) =>
POST<string>(`/core/dataset/create`, data);
export const putDatasetById = (data: DatasetUpdateParams) => PUT(`/core/dataset/update`, data);
export const delDatasetById = (id: string) => DELETE(`/core/dataset/delete?id=${id}`);
export const postSearchText = (data: SearchTestProps) =>
POST<SearchTestResponseType>(`/core/dataset/searchTest`, data);

View File

@@ -1,6 +0,0 @@
import { GET, POST, PUT, DELETE } from '../request';
import type { FetchResultItem } from '@/types/plugin';
export const fetchUrls = (urlList: string[]) =>
POST<FetchResultItem[]>(`/plugins/urlFetch`, { urlList });

View File

@@ -1,18 +0,0 @@
import { GET, POST } from '../request';
import { AxiosProgressEvent } from 'axios';
export const uploadImg = (base64Img: string) => POST<string>('/system/uploadImage', { base64Img });
export const postUploadFiles = (
data: FormData,
onUploadProgress: (progressEvent: AxiosProgressEvent) => void
) =>
POST<string[]>('/support/file/upload', data, {
onUploadProgress,
headers: {
'Content-Type': 'multipart/form-data; charset=utf-8'
}
});
export const getFileViewUrl = (fileId: string) => GET<string>('/support/file/readUrl', { fileId });

View File

@@ -1,4 +0,0 @@
import { GET, POST, PUT } from './request';
import type { InitDateResponse } from '@/pages/api/system/getInitData';
export const getInitData = () => GET<InitDateResponse>('/system/getInitData');

View File

@@ -1,9 +1,9 @@
import React, { useRef } from 'react';
import { ModalBody, Textarea, ModalFooter, Button } from '@chakra-ui/react';
import MyModal from '../MyModal';
import { useRequest } from '@/hooks/useRequest';
import { useRequest } from '@/web/common/hooks/useRequest';
import { useTranslation } from 'next-i18next';
import { userUpdateChatFeedback } from '@/api/chat';
import { userUpdateChatFeedback } from '@/web/core/api/chat';
const FeedbackModal = ({
chatItemId,

View File

@@ -1,8 +1,8 @@
import React, { useCallback, useMemo, useState } from 'react';
import { ModalBody, Box, useTheme, Flex, Progress } from '@chakra-ui/react';
import { getDatasetDataItemById } from '@/api/core/dataset/data';
import { useLoading } from '@/hooks/useLoading';
import { useToast } from '@/hooks/useToast';
import { getDatasetDataItemById } from '@/web/core/api/dataset';
import { useLoading } from '@/web/common/hooks/useLoading';
import { useToast } from '@/web/common/hooks/useToast';
import { getErrText } from '@/utils/tools';
import { QuoteItemType } from '@/types/chat';
import MyIcon from '@/components/Icon';

View File

@@ -1,9 +1,9 @@
import React from 'react';
import { ModalBody, ModalFooter, Button } from '@chakra-ui/react';
import MyModal from '../MyModal';
import { useRequest } from '@/hooks/useRequest';
import { useRequest } from '@/web/common/hooks/useRequest';
import { useTranslation } from 'next-i18next';
import { userUpdateChatFeedback } from '@/api/chat';
import { userUpdateChatFeedback } from '@/web/core/api/chat';
const ReadFeedbackModal = ({
chatItemId,

View File

@@ -2,7 +2,7 @@ import React, { useCallback, useMemo, useState } from 'react';
import { ChatHistoryItemResType, ChatItemType, QuoteItemType } from '@/types/chat';
import { Flex, BoxProps, useDisclosure } from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';
import { useGlobalStore } from '@/store/global';
import { useGlobalStore } from '@/web/common/store/global';
import dynamic from 'next/dynamic';
import Tag from '../Tag';
import MyTooltip from '../MyTooltip';

View File

@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { ModalBody, useTheme, ModalFooter, Button, Box, Card, Flex, Grid } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import { useToast } from '@/hooks/useToast';
import { useToast } from '@/web/common/hooks/useToast';
import Avatar from '../Avatar';
import MyIcon from '@/components/Icon';
import { KbTypeEnum } from '@/constants/dataset';

View File

@@ -15,10 +15,10 @@ import {
ChatSiteItemType,
ExportChatType
} from '@/types/chat';
import { useToast } from '@/hooks/useToast';
import { useAudioPlay } from '@/utils/web/voice';
import { useToast } from '@/web/common/hooks/useToast';
import { useAudioPlay } from '@/web/common/utils/voice';
import { getErrText } from '@/utils/tools';
import { useCopyData } from '@/hooks/useCopyData';
import { useCopyData } from '@/web/common/hooks/useCopyData';
import {
Box,
Card,
@@ -30,22 +30,22 @@ import {
BoxProps,
FlexProps
} from '@chakra-ui/react';
import { feConfigs } from '@/store/static';
import { event } from '@/utils/plugin/eventbus';
import { feConfigs } from '@/web/common/store/static';
import { eventBus } from '@/web/common/utils/eventbus';
import { adaptChat2GptMessages } from '@/utils/common/adapt/message';
import { useMarkdown } from '@/hooks/useMarkdown';
import { useMarkdown } from '@/web/common/hooks/useMarkdown';
import { AppModuleItemType } from '@/types/app';
import { VariableInputEnum } from '@/constants/app';
import { useForm } from 'react-hook-form';
import type { MessageItemType } from '@/types/core/chat/type';
import { fileDownload } from '@/utils/web/file';
import { fileDownload } from '@/web/common/utils/file';
import { htmlTemplate } from '@/constants/common';
import { useRouter } from 'next/router';
import { useGlobalStore } from '@/store/global';
import { useGlobalStore } from '@/web/common/store/global';
import { TaskResponseKeyEnum } from '@/constants/chat';
import { useTranslation } from 'react-i18next';
import { customAlphabet } from 'nanoid';
import { userUpdateChatFeedback, adminUpdateChatFeedback } from '@/api/chat';
import { userUpdateChatFeedback, adminUpdateChatFeedback } from '@/web/core/api/chat';
import MyIcon from '@/components/Icon';
import Avatar from '@/components/Avatar';
@@ -61,7 +61,7 @@ const InputDataModal = dynamic(() => import('@/pages/kb/detail/components/InputD
import styles from './index.module.scss';
import Script from 'next/script';
import { postQuestionGuide } from '@/api/core/ai/agent/api';
import { postQuestionGuide } from '@/web/core/api/ai';
import { splitGuideModule } from './utils';
import { DatasetSpecialIdEnum } from '@fastgpt/core/dataset/constant';
@@ -518,13 +518,13 @@ const ChatBox = (
}
};
window.addEventListener('message', windowMessage);
event.on('guideClick', ({ text }: { text: string }) => {
eventBus.on('guideClick', ({ text }: { text: string }) => {
if (!text) return;
handleSubmit((data) => sendPrompt(data, text))();
});
return () => {
event.off('guideClick');
eventBus.off('guideClick');
window.removeEventListener('message', windowMessage);
};
}, [handleSubmit, sendPrompt]);

View File

@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { Menu, MenuButton, MenuItem, MenuList, MenuButtonProps } from '@chakra-ui/react';
import { getLangStore, LangEnum, setLangStore, langMap } from '@/utils/web/i18n';
import { getLangStore, LangEnum, setLangStore, langMap } from '@/web/common/utils/i18n';
import MyIcon from '@/components/Icon';
import { useTranslation } from 'react-i18next';
import { useRouter } from 'next/router';

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { useRouter } from 'next/router';
import { useToast } from '@chakra-ui/react';
import { useUserStore } from '@/store/user';
import { useUserStore } from '@/web/support/store/user';
import { useQuery } from '@tanstack/react-query';
const unAuthPage: { [key: string]: boolean } = {

View File

@@ -1,15 +1,15 @@
import React, { useEffect, useMemo } from 'react';
import { Box, useColorMode, Flex } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import { useLoading } from '@/hooks/useLoading';
import { useGlobalStore } from '@/store/global';
import { useLoading } from '@/web/common/hooks/useLoading';
import { useGlobalStore } from '@/web/common/store/global';
import { throttle } from 'lodash';
import Auth from './auth';
import Navbar from './navbar';
import NavbarPhone from './navbarPhone';
import { useQuery } from '@tanstack/react-query';
import { useUserStore } from '@/store/user';
import { getUnreadCount } from '@/api/user';
import { useUserStore } from '@/web/support/store/user';
import { getUnreadCount } from '@/web/support/api/user';
const pcUnShowLayoutRoute: Record<string, boolean> = {
'/': true,

View File

@@ -1,16 +1,16 @@
import React, { useMemo } from 'react';
import { Box, Flex, Link } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import { useUserStore } from '@/store/user';
import { useChatStore } from '@/store/chat';
import { useUserStore } from '@/web/support/store/user';
import { useChatStore } from '@/web/core/store/chat';
import { HUMAN_ICON } from '@/constants/chat';
import { feConfigs } from '@/store/static';
import { feConfigs } from '@/web/common/store/static';
import NextLink from 'next/link';
import Badge from '../Badge';
import Avatar from '../Avatar';
import MyIcon from '../Icon';
import { useTranslation } from 'next-i18next';
import { useGlobalStore } from '@/store/global';
import { useGlobalStore } from '@/web/common/store/global';
import MyTooltip from '../MyTooltip';
export enum NavbarTypeEnum {

View File

@@ -1,7 +1,7 @@
import React, { useMemo } from 'react';
import { useRouter } from 'next/router';
import { Flex, Box } from '@chakra-ui/react';
import { useChatStore } from '@/store/chat';
import { useChatStore } from '@/web/core/store/chat';
import { useTranslation } from 'react-i18next';
import Badge from '../Badge';
import MyIcon from '../Icon';

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { Box, Flex, useColorModeValue } from '@chakra-ui/react';
import Icon from '@/components/Icon';
import { useCopyData } from '@/hooks/useCopyData';
import { useCopyData } from '@/web/common/hooks/useCopyData';
const codeLight: { [key: string]: React.CSSProperties } = {
'code[class*=language-]': {

View File

@@ -5,7 +5,7 @@ import RemarkGfm from 'remark-gfm';
import RemarkMath from 'remark-math';
import RehypeKatex from 'rehype-katex';
import RemarkBreaks from 'remark-breaks';
import { event } from '@/utils/plugin/eventbus';
import { eventBus } from '@/web/common/utils/eventbus';
import 'katex/dist/katex.min.css';
import styles from '../index.module.scss';
@@ -27,7 +27,7 @@ function MyLink(e: any) {
textDecoration={'underline'}
cursor={'pointer'}
onClick={() => {
event.emit('guideClick', { text });
eventBus.emit('guideClick', { text });
}}
>
{text}

View File

@@ -1,7 +1,7 @@
import React, { useMemo } from 'react';
import { Box, useTheme } from '@chakra-ui/react';
import { getFileAndOpen } from '@/utils/web/file';
import { useToast } from '@/hooks/useToast';
import { getFileAndOpen } from '@/web/common/utils/file';
import { useToast } from '@/web/common/hooks/useToast';
import { getErrText } from '@/utils/tools';
type QuoteItemType = {

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { Tooltip, TooltipProps } from '@chakra-ui/react';
import { useGlobalStore } from '@/store/global';
import { useGlobalStore } from '@/web/common/store/global';
interface Props extends TooltipProps {
forceShow?: boolean;

View File

@@ -1,9 +1,9 @@
import { getDatasets, getDatasetPaths } from '@/api/core/dataset';
import { getDatasets, getDatasetPaths } from '@/web/core/api/dataset';
import MyModal from '@/components/MyModal';
import { useQuery } from '@tanstack/react-query';
import React, { Dispatch, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useGlobalStore } from '@/store/global';
import { useGlobalStore } from '@/web/common/store/global';
import { Box, Flex, ModalHeader } from '@chakra-ui/react';
import MyIcon from '@/components/Icon';

View File

@@ -25,19 +25,19 @@ import {
createAOpenApiKey,
delOpenApiById,
putOpenApiKey
} from '@/api/support/openapi';
import type { EditApiKeyProps } from '@/api/support/openapi/index.d';
} from '@/web/support/api/openapi';
import type { EditApiKeyProps } from '@/global/support/api/openapiReq';
import { useQuery, useMutation } from '@tanstack/react-query';
import { useLoading } from '@/hooks/useLoading';
import { useLoading } from '@/web/common/hooks/useLoading';
import dayjs from 'dayjs';
import { AddIcon, QuestionOutlineIcon } from '@chakra-ui/icons';
import { useCopyData } from '@/hooks/useCopyData';
import { feConfigs } from '@/store/static';
import { useCopyData } from '@/web/common/hooks/useCopyData';
import { feConfigs } from '@/web/common/store/static';
import { useTranslation } from 'react-i18next';
import MyIcon from '@/components/Icon';
import MyModal from '@/components/MyModal';
import { useForm } from 'react-hook-form';
import { useRequest } from '@/hooks/useRequest';
import { useRequest } from '@/web/common/hooks/useRequest';
import MyTooltip from '@/components/MyTooltip';
type EditProps = EditApiKeyProps & { _id?: string };

View File

@@ -7,6 +7,9 @@ export enum SystemInputEnum {
'userChatInput' = 'userChatInput',
'questionGuide' = 'questionGuide'
}
export enum SystemOutputEnum {
finish = 'finish'
}
export enum VariableInputEnum {
input = 'input',

View File

@@ -9,13 +9,14 @@ import {
} from './index';
import type { AppItemType } from '@/types/app';
import type { FlowModuleTemplateType } from '@/types/core/app/flow';
import { chatModelList } from '@/store/static';
import { chatModelList } from '@/web/common/store/static';
import {
Input_Template_History,
Input_Template_TFSwitch,
Input_Template_UserChatInput
} from './inputTemplate';
import { ContextExtractEnum, HttpPropsEnum } from './flowField';
import { Output_Template_Finish } from './outputTemplate';
export const ChatModelSystemTip =
'模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}';
@@ -130,12 +131,15 @@ export const ChatModule: FlowModuleTemplateType = {
intro: 'AI 大模型对话',
showStatus: true,
inputs: [
Input_Template_TFSwitch,
{
key: 'model',
type: FlowInputItemTypeEnum.custom,
type: FlowInputItemTypeEnum.selectChatModel,
label: '对话模型',
value: chatModelList[0]?.model,
list: chatModelList.map((item) => ({ label: item.name, value: item.model }))
list: chatModelList.map((item) => ({ label: item.name, value: item.model })),
required: true,
valueCheck: (val) => !!val
},
{
key: 'temperature',
@@ -152,7 +156,7 @@ export const ChatModule: FlowModuleTemplateType = {
},
{
key: 'maxToken',
type: FlowInputItemTypeEnum.custom,
type: FlowInputItemTypeEnum.maxToken,
label: '回复上限',
value: chatModelList[0] ? chatModelList[0].contextMaxToken / 2 : 2000,
min: 100,
@@ -190,10 +194,9 @@ export const ChatModule: FlowModuleTemplateType = {
valueType: FlowValueTypeEnum.string,
value: ''
},
Input_Template_TFSwitch,
{
key: 'quoteQA',
type: FlowInputItemTypeEnum.custom,
type: FlowInputItemTypeEnum.quoteList,
label: '引用内容',
description: "对象数组格式,结构:\n [{q:'问题',a:'回答'}]",
valueType: FlowValueTypeEnum.kbQuote,
@@ -219,14 +222,7 @@ export const ChatModule: FlowModuleTemplateType = {
type: FlowOutputItemTypeEnum.source,
targets: []
},
{
key: 'finish',
label: '回复结束',
description: 'AI 回复完成后触发',
valueType: FlowValueTypeEnum.boolean,
type: FlowOutputItemTypeEnum.source,
targets: []
}
Output_Template_Finish
]
};
@@ -237,12 +233,15 @@ export const KBSearchModule: FlowModuleTemplateType = {
intro: '去知识库中搜索对应的答案。可作为 AI 对话引用参考。',
showStatus: true,
inputs: [
Input_Template_TFSwitch,
{
key: 'kbList',
type: FlowInputItemTypeEnum.custom,
type: FlowInputItemTypeEnum.selectDataset,
label: '关联的知识库',
value: [],
list: []
list: [],
required: true,
valueCheck: (val) => !!val.length
},
{
key: 'similarity',
@@ -271,7 +270,6 @@ export const KBSearchModule: FlowModuleTemplateType = {
{ label: '20', value: 20 }
]
},
Input_Template_TFSwitch,
Input_Template_UserChatInput
],
outputs: [
@@ -297,7 +295,8 @@ export const KBSearchModule: FlowModuleTemplateType = {
type: FlowOutputItemTypeEnum.source,
valueType: FlowValueTypeEnum.kbQuote,
targets: []
}
},
Output_Template_Finish
]
};
@@ -312,23 +311,14 @@ export const AnswerModule: FlowModuleTemplateType = {
{
key: SpecialInputKeyEnum.answerText,
type: FlowInputItemTypeEnum.textarea,
valueType: FlowValueTypeEnum.string,
valueType: FlowValueTypeEnum.any,
value: '',
label: '回复的内容',
description:
'可以使用 \\n 来实现连续换行。\n\n可以通过外部模块输入实现回复外部模块输入时会覆盖当前填写的内容'
'可以使用 \\n 来实现连续换行。\n\n可以通过外部模块输入实现回复外部模块输入时会覆盖当前填写的内容。\n\n如传入非字符串类型数据将会自动转成字符串'
}
],
outputs: [
{
key: 'finish',
label: '回复结束',
description: '回复完成后触发',
valueType: FlowValueTypeEnum.boolean,
type: FlowOutputItemTypeEnum.source,
targets: []
}
]
outputs: [Output_Template_Finish]
};
export const ClassifyQuestionModule: FlowModuleTemplateType = {
flowType: FlowModuleTypeEnum.classifyQuestion,
@@ -461,6 +451,7 @@ export const HttpModule: FlowModuleTemplateType = {
description: '可以发出一个 HTTP POST 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
showStatus: true,
inputs: [
Input_Template_TFSwitch,
{
key: HttpPropsEnum.url,
value: '',
@@ -468,19 +459,11 @@ export const HttpModule: FlowModuleTemplateType = {
label: '请求地址',
description: '请求目标地址',
placeholder: 'https://api.fastgpt.run/getInventory',
required: true
},
Input_Template_TFSwitch
],
outputs: [
{
key: HttpPropsEnum.finish,
label: '请求结束',
valueType: FlowValueTypeEnum.boolean,
type: FlowOutputItemTypeEnum.source,
targets: []
required: true,
valueCheck: (val) => !!val
}
]
],
outputs: [Output_Template_Finish]
};
export const EmptyModule: FlowModuleTemplateType = {
flowType: FlowModuleTypeEnum.empty,
@@ -527,13 +510,7 @@ export const AppModule: FlowModuleTemplateType = {
type: FlowOutputItemTypeEnum.source,
targets: []
},
{
key: 'finish',
label: '请求结束',
valueType: FlowValueTypeEnum.boolean,
type: FlowOutputItemTypeEnum.source,
targets: []
}
Output_Template_Finish
]
};

View File

@@ -8,17 +8,21 @@ export enum FlowInputItemTypeEnum {
select = 'select',
slider = 'slider',
custom = 'custom',
target = 'target',
none = 'none',
target = 'target', // data input
switch = 'switch',
hidden = 'hidden',
selectApp = 'selectApp'
selectApp = 'selectApp',
// chat special input
quoteList = 'quoteList',
maxToken = 'maxToken',
selectChatModel = 'selectChatModel',
// dataset special input
selectDataset = 'selectDataset',
hidden = 'hidden'
}
export enum FlowOutputItemTypeEnum {
answer = 'answer',
source = 'source',
none = 'none',
hidden = 'hidden'
}

View File

@@ -0,0 +1,12 @@
import type { FlowOutputItemType } from '@/types/core/app/flow';
import { SystemOutputEnum } from '../app';
import { FlowOutputItemTypeEnum, FlowValueTypeEnum } from './index';
export const Output_Template_Finish: FlowOutputItemType = {
key: SystemOutputEnum.finish,
label: '模块调用结束',
description: '模块调用结束时触发',
valueType: FlowValueTypeEnum.boolean,
type: FlowOutputItemTypeEnum.source,
targets: []
};

View File

@@ -0,0 +1,14 @@
import {
type QAModelItemType,
type ChatModelItemType,
type VectorModelItemType,
FunctionModelItemType
} from '@/types/model';
export type InitDateResponse = {
chatModels: ChatModelItemType[];
qaModel: QAModelItemType;
vectorModels: VectorModelItemType[];
feConfigs: FeConfigsType;
systemVersion: string;
};

View File

@@ -1,6 +1,6 @@
import { ChatCompletionRequestMessage } from '@fastgpt/core/ai/type';
export type CreateQuestionGuideProps = {
export type CreateQuestionGuideParams = {
messages: ChatCompletionRequestMessage[];
shareId?: string;
};

View File

@@ -2,7 +2,7 @@ import type { AppSchema } from '@/types/mongoSchema';
import type { ChatItemType } from '@/types/chat';
import { AppModuleItemType, VariableItemType } from '@/types/app';
export interface InitChatResponse {
export type InitChatResponse = {
chatId: string;
appId: string;
app: {
@@ -16,9 +16,4 @@ export interface InitChatResponse {
title: string;
variables: Record<string, any>;
history: ChatItemType[];
}
export interface InitShareChatResponse {
userAvatar: string;
app: InitChatResponse['app'];
}
};

View File

@@ -0,0 +1,59 @@
import { KbTypeEnum } from '@/constants/dataset';
import type { RequestPaging } from '@/types';
import { TrainingModeEnum } from '@/constants/plugin';
import type { SearchTestItemType } from '@/types/core/dataset';
import { DatasetDataItemType } from '@/types/core/dataset/data';
/* ===== dataset ===== */
export type DatasetUpdateParams = {
id: string;
parentId?: string;
tags?: string;
name?: string;
avatar?: string;
};
export type CreateDatasetParams = {
parentId?: string;
name: string;
tags: string[];
avatar: string;
vectorModel?: string;
type: `${KbTypeEnum}`;
};
export type SearchTestProps = {
kbId: string;
text: string;
};
/* ======= file =========== */
export type GetFileListProps = RequestPaging & {
kbId: string;
searchText: string;
};
export type UpdateFileProps = { id: string; name?: string; datasetUsed?: boolean };
export type MarkFileUsedProps = { fileIds: string[] };
/* ==== data ===== */
export type PushDataProps = {
kbId: string;
data: DatasetDataItemType[];
mode: `${TrainingModeEnum}`;
prompt?: string;
billId?: string;
};
export type UpdateDatasetDataPrams = {
dataId: string;
kbId: string;
a?: string;
q?: string;
};
export type GetDatasetDataListProps = RequestPaging & {
kbId: string;
searchText: string;
fileId: string;
};

View File

@@ -0,0 +1,15 @@
import { KbTypeEnum } from '@/constants/dataset';
import type { RequestPaging } from '@/types';
import { TrainingModeEnum } from '@/constants/plugin';
import type { SearchTestItemType } from '@/types/core/dataset';
import { DatasetDataItemType } from '@/types/core/dataset/data';
/* ===== dataset ===== */
export type SearchTestResponseType = SearchTestItemType['results'];
/* ======= file =========== */
/* ==== data ===== */
export type PushDataResponse = {
insertLen: number;
};

View File

@@ -0,0 +1,6 @@
import type { InitChatResponse } from '@/global/core/api/chatRes.d';
export type InitShareChatResponse = {
userAvatar: string;
app: InitChatResponse['app'];
};

View File

@@ -4,18 +4,18 @@ import Script from 'next/script';
import Head from 'next/head';
import { ChakraProvider, ColorModeScript } from '@chakra-ui/react';
import Layout from '@/components/Layout';
import { theme } from '@/constants/theme';
import { theme } from '@/web/styles/theme';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import NProgress from 'nprogress'; //nprogress module
import Router from 'next/router';
import { clientInitData, feConfigs } from '@/store/static';
import { clientInitData, feConfigs } from '@/web/common/store/static';
import { appWithTranslation, useTranslation } from 'next-i18next';
import { getLangStore, setLangStore } from '@/utils/web/i18n';
import { getLangStore, setLangStore } from '@/web/common/utils/i18n';
import { useRouter } from 'next/router';
import { useGlobalStore } from '@/store/global';
import { useGlobalStore } from '@/web/common/store/global';
import 'nprogress/nprogress.css';
import '@/styles/reset.scss';
import '@/web/styles/reset.scss';
import { FeConfigsType } from '@/types';
//Binding events.

View File

@@ -1,7 +1,7 @@
import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { serviceSideProps } from '@/utils/web/i18n';
import { useGlobalStore } from '@/store/global';
import { serviceSideProps } from '@/web/common/utils/i18n';
import { useGlobalStore } from '@/web/common/store/global';
import { addLog } from '@/service/utils/tools';
import { getErrText } from '@/utils/tools';

View File

@@ -12,16 +12,16 @@ import {
Button
} from '@chakra-ui/react';
import { BillSourceMap } from '@/constants/user';
import { getUserBills } from '@/api/user';
import { getUserBills } from '@/web/common/api/bill';
import type { UserBillType } from '@/types/user';
import { usePagination } from '@/hooks/usePagination';
import { useLoading } from '@/hooks/useLoading';
import { usePagination } from '@/web/common/hooks/usePagination';
import { useLoading } from '@/web/common/hooks/useLoading';
import dayjs from 'dayjs';
import MyIcon from '@/components/Icon';
import DateRangePicker, { type DateRangeType } from '@/components/DateRangePicker';
import { addDays } from 'date-fns';
import dynamic from 'next/dynamic';
import { useGlobalStore } from '@/store/global';
import { useGlobalStore } from '@/web/common/store/global';
import { useTranslation } from 'next-i18next';
const BillDetail = dynamic(() => import('./BillDetail'));

View File

@@ -14,21 +14,21 @@ import {
} from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { UserUpdateParams } from '@/types/user';
import { useToast } from '@/hooks/useToast';
import { useUserStore } from '@/store/user';
import { useToast } from '@/web/common/hooks/useToast';
import { useUserStore } from '@/web/support/store/user';
import { UserType } from '@/types/user';
import { useQuery } from '@tanstack/react-query';
import dynamic from 'next/dynamic';
import { useSelectFile } from '@/hooks/useSelectFile';
import { compressImg } from '@/utils/web/file';
import { feConfigs, systemVersion } from '@/store/static';
import { useSelectFile } from '@/web/common/hooks/useSelectFile';
import { compressImg } from '@/web/common/utils/file';
import { feConfigs, systemVersion } from '@/web/common/store/static';
import { useTranslation } from 'next-i18next';
import { timezoneList } from '@/utils/user';
import Loading from '@/components/Loading';
import Avatar from '@/components/Avatar';
import MyIcon from '@/components/Icon';
import MyTooltip from '@/components/MyTooltip';
import { getLangStore, LangEnum, langMap, setLangStore } from '@/utils/web/i18n';
import { getLangStore, LangEnum, langMap, setLangStore } from '@/web/common/utils/i18n';
import { useRouter } from 'next/router';
import MyMenu from '@/components/MyMenu';
import MySelect from '@/components/Select';

View File

@@ -1,11 +1,11 @@
import React from 'react';
import { Box, Flex, useTheme } from '@chakra-ui/react';
import { getInforms, readInform } from '@/api/user';
import { usePagination } from '@/hooks/usePagination';
import { useLoading } from '@/hooks/useLoading';
import { getInforms, readInform } from '@/web/support/api/user';
import { usePagination } from '@/web/common/hooks/usePagination';
import { useLoading } from '@/web/common/hooks/useLoading';
import type { informSchema } from '@/types/mongoSchema';
import { formatTimeToChatTime } from '@/utils/tools';
import { useGlobalStore } from '@/store/global';
import { useGlobalStore } from '@/web/common/store/global';
import MyIcon from '@/components/Icon';
const BillTable = () => {

View File

@@ -3,7 +3,7 @@ import { ModalBody, Box, Flex, Input, ModalFooter, Button } from '@chakra-ui/rea
import MyModal from '@/components/MyModal';
import { useTranslation } from 'react-i18next';
import { useForm } from 'react-hook-form';
import { useRequest } from '@/hooks/useRequest';
import { useRequest } from '@/web/common/hooks/useRequest';
import { UserType } from '@/types/user';
const OpenAIAccountModal = ({
@@ -32,7 +32,8 @@ const OpenAIAccountModal = ({
<MyModal isOpen onClose={onClose} title={t('user.OpenAI Account Setting')}>
<ModalBody>
<Box fontSize={'sm'} color={'myGray.500'}>
线使 OpenAI Chat
OpenAI key OneAPI 线使 OpenAI
Chat Key 访
</Box>
<Flex alignItems={'center'} mt={5}>
<Box flex={'0 0 65px'}>API Key:</Box>

View File

@@ -1,7 +1,7 @@
import React, { useState, useCallback } from 'react';
import { ModalFooter, ModalBody, Button, Input, Box, Grid } from '@chakra-ui/react';
import { getPayCode, checkPayResult } from '@/api/user';
import { useToast } from '@/hooks/useToast';
import { getPayCode, checkPayResult } from '@/web/common/api/bill';
import { useToast } from '@/web/common/hooks/useToast';
import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import { getErrText } from '@/utils/tools';
@@ -9,7 +9,7 @@ import { useTranslation } from 'react-i18next';
import { formatPrice } from '@fastgpt/common/bill/index';
import Markdown from '@/components/Markdown';
import MyModal from '@/components/MyModal';
import { vectorModelList, chatModelList, qaModel } from '@/store/static';
import { vectorModelList, chatModelList, qaModel } from '@/web/common/store/static';
const PayModal = ({ onClose }: { onClose: () => void }) => {
const router = useRouter();

View File

@@ -11,13 +11,13 @@ import {
Flex,
Box
} from '@chakra-ui/react';
import { getPayOrders, checkPayResult } from '@/api/user';
import { getPayOrders, checkPayResult } from '@/web/common/api/bill';
import { PaySchema } from '@/types/mongoSchema';
import dayjs from 'dayjs';
import { useQuery } from '@tanstack/react-query';
import { formatPrice } from '@fastgpt/common/bill/index';
import { useToast } from '@/hooks/useToast';
import { useLoading } from '@/hooks/useLoading';
import { useToast } from '@/web/common/hooks/useToast';
import { useLoading } from '@/web/common/hooks/useLoading';
import MyIcon from '@/components/Icon';
const PayRecordTable = () => {

View File

@@ -16,15 +16,15 @@ import {
} from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import { useQuery } from '@tanstack/react-query';
import { getPromotionInitData, getPromotionRecords } from '@/api/user';
import { useUserStore } from '@/store/user';
import { useLoading } from '@/hooks/useLoading';
import { getPromotionInitData, getPromotionRecords } from '@/web/support/api/user';
import { useUserStore } from '@/web/support/store/user';
import { useLoading } from '@/web/common/hooks/useLoading';
import MyTooltip from '@/components/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { useCopyData } from '@/hooks/useCopyData';
import { usePagination } from '@/hooks/usePagination';
import { PromotionRecordType } from '@/api/response/user';
import { useCopyData } from '@/web/common/hooks/useCopyData';
import { usePagination } from '@/web/common/hooks/usePagination';
import type { PromotionRecordType } from '@/global/support/api/userRes.d';
import MyIcon from '@/components/Icon';
import dayjs from 'dayjs';

View File

@@ -3,8 +3,8 @@ import { ModalBody, Box, Flex, Input, ModalFooter, Button } from '@chakra-ui/rea
import MyModal from '@/components/MyModal';
import { useTranslation } from 'react-i18next';
import { useForm } from 'react-hook-form';
import { useRequest } from '@/hooks/useRequest';
import { updatePasswordByOld } from '@/api/user';
import { useRequest } from '@/web/common/hooks/useRequest';
import { updatePasswordByOld } from '@/web/support/api/user';
type FormType = {
oldPsw: string;

View File

@@ -1,17 +1,17 @@
import React, { useCallback, useRef } from 'react';
import { Box, Flex, useTheme } from '@chakra-ui/react';
import { useGlobalStore } from '@/store/global';
import { useGlobalStore } from '@/web/common/store/global';
import { useRouter } from 'next/router';
import dynamic from 'next/dynamic';
import { clearToken } from '@/utils/user';
import { useUserStore } from '@/store/user';
import { useConfirm } from '@/hooks/useConfirm';
import { useUserStore } from '@/web/support/store/user';
import { useConfirm } from '@/web/common/hooks/useConfirm';
import PageContainer from '@/components/PageContainer';
import SideTabs from '@/components/SideTabs';
import Tabs from '@/components/Tabs';
import UserInfo from './components/Info';
import { serviceSideProps } from '@/utils/web/i18n';
import { feConfigs } from '@/store/static';
import { serviceSideProps } from '@/web/common/utils/i18n';
import { feConfigs } from '@/web/common/store/static';
import { useTranslation } from 'react-i18next';
import Script from 'next/script';

View File

@@ -6,7 +6,7 @@ import type { PagingData } from '@/types';
import { AppLogsListItemType } from '@/types/app';
import { Types } from 'mongoose';
import { addDays } from 'date-fns';
import { GetAppChatLogsParams } from '@/api/request/app';
import type { GetAppChatLogsParams } from '@/global/core/api/appReq.d';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {

View File

@@ -1,7 +1,7 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, ChatItem } from '@/service/mongo';
import { AdminUpdateFeedbackParams } from '@/api/request/chat';
import type { AdminUpdateFeedbackParams } from '@/global/core/api/chatReq.d';
import { authUser } from '@/service/utils/auth';
/* 初始化我的聊天框,需要身份验证 */

View File

@@ -1,7 +1,7 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { Chat, ChatItem } from '@/service/mongo';
import type { InitChatResponse } from '@/api/response/chat';
import type { InitChatResponse } from '@/global/core/api/chatRes.d';
import { authUser } from '@/service/utils/auth';
import { ChatItemType } from '@/types/chat';
import { authApp } from '@/service/utils/auth';

View File

@@ -3,7 +3,7 @@ import { jsonRes } from '@/service/response';
import { connectToDatabase, Bill } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { BillSourceEnum } from '@/constants/user';
import { CreateTrainingBillType } from '@/api/common/bill/index.d';
import { CreateTrainingBillType } from '@/global/common/api/billReq.d';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {

View File

@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { CreateQuestionGuideProps } from '@/api/core/ai/agent/type';
import type { CreateQuestionGuideParams } from '@/global/core/api/aiReq.d';
import { pushQuestionGuideBill } from '@/service/common/bill/push';
import { defaultQGModel } from '@/pages/api/system/getInitData';
import { createQuestionGuide } from '@fastgpt/core/ai/functions/createQuestionGuide';
@@ -10,7 +10,7 @@ import { createQuestionGuide } from '@fastgpt/core/ai/functions/createQuestionGu
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
await connectToDatabase();
const { messages } = req.body as CreateQuestionGuideProps;
const { messages } = req.body as CreateQuestionGuideParams;
const { user } = await authUser({
req,
authOutLink: true,

View File

@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, KB } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import type { CreateDatasetParams } from '@/api/core/dataset/index.d';
import type { CreateDatasetParams } from '@/global/core/api/datasetReq.d';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {

View File

@@ -10,7 +10,8 @@ import { startQueue } from '@/service/utils/tools';
import { getVectorModel } from '@/service/utils/data';
import { DatasetDataItemType } from '@/types/core/dataset/data';
import { countPromptTokens } from '@/utils/common/tiktoken';
import type { PushDataProps, PushDataResponse } from '@/api/core/dataset/data.d';
import type { PushDataResponse } from '@/global/core/api/datasetRes.d';
import type { PushDataProps } from '@/global/core/api/datasetReq.d';
import { authFileIdValid } from '@/service/dataset/auth';
const modeMap = {

View File

@@ -6,11 +6,11 @@ import { withNextCors } from '@/service/utils/tools';
import { KB, connectToDatabase } from '@/service/mongo';
import { getVector } from '@/pages/api/openapi/plugin/vector';
import { PgDatasetTableName } from '@/constants/plugin';
import type { UpdateDataPrams } from '@/api/core/dataset/data.d';
import type { UpdateDatasetDataPrams } from '@/global/core/api/datasetReq.d';
export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
const { dataId, a = '', q = '', kbId } = req.body as UpdateDataPrams;
const { dataId, a = '', q = '', kbId } = req.body as UpdateDatasetDataPrams;
if (!dataId) {
throw new Error('缺少参数');

View File

@@ -3,7 +3,7 @@ import { jsonRes } from '@/service/response';
import { connectToDatabase } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { GridFSStorage } from '@/service/lib/gridfs';
import { MarkFileUsedProps } from '@/api/core/dataset/file.d';
import { MarkFileUsedProps } from '@/global/core/api/datasetReq.d';
import { Types } from 'mongoose';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {

View File

@@ -3,7 +3,7 @@ import { jsonRes } from '@/service/response';
import { connectToDatabase } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { GridFSStorage } from '@/service/lib/gridfs';
import { UpdateFileProps } from '@/api/core/dataset/file.d';
import { UpdateFileProps } from '@/global/core/api/datasetReq.d';
import { Types } from 'mongoose';
import { PgClient } from '@/service/pg';
import { PgDatasetTableName } from '@/constants/plugin';

View File

@@ -6,7 +6,8 @@ import { withNextCors } from '@/service/utils/tools';
import { getVector } from '../../openapi/plugin/vector';
import { PgDatasetTableName } from '@/constants/plugin';
import { KB } from '@/service/mongo';
import type { SearchTestProps, SearchTestResponseType } from '@/api/core/dataset/index.d';
import type { SearchTestProps } from '@/global/core/api/datasetReq.d';
import type { SearchTestResponseType } from '@/global/core/api/datasetRes.d';
export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {

View File

@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, KB } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import type { DatasetUpdateParams } from '@/api/core/dataset/index.d';
import type { DatasetUpdateParams } from '@/global/core/api/datasetReq.d';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {

View File

@@ -5,7 +5,7 @@ import { JSDOM } from 'jsdom';
import { Readability } from '@mozilla/readability';
import { jsonRes } from '@/service/response';
import { authUser } from '@/service/utils/auth';
import type { FetchResultItem } from '@/types/plugin';
import type { FetchResultItem } from '@/global/common/api/pluginRes.d';
import { simpleText } from '@/utils/file';
export type UrlFetchResponse = FetchResultItem[];

View File

@@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { request } from '@/api/service/request';
import { request } from '@/service/common/api/request';
import type { Method } from 'axios';
import { connectToDatabase } from '@/service/mongo';

View File

@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, OpenApi } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import type { GetApiKeyProps } from '@/api/support/openapi/index.d';
import type { GetApiKeyProps } from '@/global/support/api/openapiReq.d';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {

View File

@@ -4,7 +4,7 @@ import { jsonRes } from '@/service/response';
import { connectToDatabase, OpenApi } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { customAlphabet } from 'nanoid';
import type { EditApiKeyProps } from '@/api/support/openapi/index.d';
import type { EditApiKeyProps } from '@/global/support/api/openapiReq.d';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {

View File

@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, OpenApi } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import type { EditApiKeyProps } from '@/api/support/openapi/index.d';
import type { EditApiKeyProps } from '@/global/support/api/openapiReq.d';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {

View File

@@ -1,7 +1,7 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, OutLink, User } from '@/service/mongo';
import type { InitShareChatResponse } from '@/api/response/chat';
import type { InitShareChatResponse } from '@/global/support/api/outLinkRes.d';
import { authApp } from '@/service/utils/auth';
import { HUMAN_ICON } from '@/constants/chat';
import { getChatModelNameList, getGuideModule } from '@/components/ChatBox/utils';

View File

@@ -28,7 +28,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
});
jsonRes(res, {
data: `/api/support/file/read?token=${token}`
data: `/api/system/file/read?token=${token}`
});
} catch (error) {
jsonRes(res, {

View File

@@ -2,20 +2,8 @@ import type { FeConfigsType, SystemEnvType } from '@/types';
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { readFileSync } from 'fs';
import {
type QAModelItemType,
type ChatModelItemType,
type VectorModelItemType,
FunctionModelItemType
} from '@/types/model';
export type InitDateResponse = {
chatModels: ChatModelItemType[];
qaModel: QAModelItemType;
vectorModels: VectorModelItemType[];
feConfigs: FeConfigsType;
systemVersion: string;
};
import type { InitDateResponse } from '@/global/common/api/systemRes';
import { type VectorModelItemType, FunctionModelItemType } from '@/types/model';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (!global.feConfigs) {

View File

@@ -15,8 +15,8 @@ import {
} from '@chakra-ui/react';
import MyTooltip from '@/components/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { defaultQuotePrompt, defaultQuoteTemplate } from '@/prompts/core/AIChat';
import { feConfigs } from '@/store/static';
import { defaultQuotePrompt, defaultQuoteTemplate } from '@/global/core/prompt/AIChat';
import { feConfigs } from '@/web/common/store/static';
const AIChatSettingsModal = ({
onClose,

View File

@@ -11,9 +11,9 @@ import React, {
import { Box, Flex, IconButton } from '@chakra-ui/react';
import MyIcon from '@/components/Icon';
import { FlowModuleTypeEnum } from '@/constants/flow';
import { streamFetch } from '@/api/fetch';
import { streamFetch } from '@/web/common/api/fetch';
import MyTooltip from '@/components/MyTooltip';
import { useUserStore } from '@/store/user';
import { useUserStore } from '@/web/support/store/user';
import ChatBox, { type ComponentRef, type StartChatFnProps } from '@/components/ChatBox';
import { getGuideModule } from '@/components/ChatBox/utils';

View File

@@ -2,7 +2,7 @@ import React, { useState } from 'react';
import { Textarea, Button, ModalBody, ModalFooter } from '@chakra-ui/react';
import MyModal from '@/components/MyModal';
import { useTranslation } from 'react-i18next';
import { useToast } from '@/hooks/useToast';
import { useToast } from '@/web/common/hooks/useToast';
import { useFlowStore } from './Provider';
const ImportSettings = ({ onClose }: { onClose: () => void }) => {

View File

@@ -6,167 +6,23 @@ import Divider from '../modules/Divider';
import Container from '../modules/Container';
import RenderInput from '../render/RenderInput';
import RenderOutput from '../render/RenderOutput';
import MySelect from '@/components/Select';
import { chatModelList } from '@/store/static';
import MySlider from '@/components/Slider';
import { Box, Button, useDisclosure } from '@chakra-ui/react';
import { formatPrice } from '@fastgpt/common/bill/index';
import MyIcon from '@/components/Icon';
import dynamic from 'next/dynamic';
import { AIChatProps } from '@/types/core/aiChat';
import { useFlowStore } from '../Provider';
const AIChatSettingsModal = dynamic(() => import('../../../AIChatSettingsModal'));
import { useFlowStore } from '../Provider';
const NodeChat = ({ data }: NodeProps<FlowModuleItemType>) => {
const { moduleId, inputs, outputs } = data;
const { onChangeNode } = useFlowStore();
const chatModulesData = useMemo(() => {
const obj: Record<string, any> = {};
inputs.forEach((item) => {
obj[item.key] = item.value;
});
return obj as AIChatProps;
}, [inputs]);
const {
isOpen: isOpenAIChatSetting,
onOpen: onOpenAIChatSetting,
onClose: onCloseAIChatSetting
} = useDisclosure();
return (
<NodeCard minW={'400px'} {...data}>
<Divider text="Input" />
<Container>
<RenderInput
moduleId={moduleId}
flowInputList={inputs}
CustomComponent={{
model: (inputItem) => {
const list = chatModelList.map((item) => {
const priceStr = `(${formatPrice(item.price, 1000)}元/1k Tokens)`;
return {
value: item.model,
label: `${item.name}${priceStr}`
};
});
return (
<MySelect
width={'100%'}
value={inputItem.value}
list={list}
onchange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: inputItem.key,
value: {
...inputItem,
value: e
}
});
// update max tokens
const model =
chatModelList.find((item) => item.model === e) || chatModelList[0];
if (!model) return;
onChangeNode({
moduleId,
type: 'inputs',
key: 'maxToken',
value: {
...inputs.find((input) => input.key === 'maxToken'),
markList: [
{ label: '100', value: 100 },
{ label: `${model.contextMaxToken}`, value: model.contextMaxToken }
],
max: model.contextMaxToken,
value: model.contextMaxToken / 2
}
});
}}
/>
);
},
maxToken: (inputItem) => {
const model = inputs.find((item) => item.key === 'model')?.value;
const modelData = chatModelList.find((item) => item.model === model);
const maxToken = modelData ? modelData.contextMaxToken : 4000;
const markList = [
{ label: '100', value: 100 },
{ label: `${maxToken}`, value: maxToken }
];
return (
<Box pt={5} pb={4} px={2}>
<MySlider
markList={markList}
width={'100%'}
min={inputItem.min || 100}
max={maxToken}
step={inputItem.step || 1}
value={inputItem.value}
onChange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: inputItem.key,
value: {
...inputItem,
value: e
}
});
}}
/>
</Box>
);
},
quoteQA: (inputItem) => {
return (
<Button
variant={'base'}
leftIcon={<MyIcon name={'settingLight'} w={'14px'} />}
onClick={onOpenAIChatSetting}
>
</Button>
);
}
}}
/>
<RenderInput moduleId={moduleId} flowInputList={inputs} />
</Container>
<Divider text="Output" />
<Container>
<RenderOutput moduleId={moduleId} flowOutputList={outputs} />
</Container>
{isOpenAIChatSetting && (
<AIChatSettingsModal
onClose={onCloseAIChatSetting}
onSuccess={(e) => {
for (let key in e) {
const item = inputs.find((input) => input.key === key);
if (!item) continue;
onChangeNode({
moduleId,
type: 'inputs',
key,
value: {
...item,
// @ts-ignore
value: e[key]
}
});
}
onCloseAIChatSetting();
}}
defaultData={chatModulesData}
/>
)}
</NodeCard>
);
};

View File

@@ -1,104 +1,20 @@
import React, { useMemo } from 'react';
import { NodeProps } from 'reactflow';
import { FlowModuleItemType } from '@/types/core/app/flow';
import { Flex, Box, Button, useTheme, useDisclosure, Grid } from '@chakra-ui/react';
import { useDatasetStore } from '@/store/dataset';
import { useQuery } from '@tanstack/react-query';
import NodeCard from '../modules/NodeCard';
import Divider from '../modules/Divider';
import Container from '../modules/Container';
import RenderInput from '../render/RenderInput';
import RenderOutput from '../render/RenderOutput';
import { DatasetSelectModal } from '../../../DatasetSelectModal';
import type { SelectedDatasetType } from '@/types/core/dataset';
import Avatar from '@/components/Avatar';
import { useFlowStore } from '../Provider';
const KBSelect = ({
activeKbs = [],
onChange
}: {
activeKbs: SelectedDatasetType;
onChange: (e: SelectedDatasetType) => void;
}) => {
const theme = useTheme();
const { allDatasets, loadAllDatasets } = useDatasetStore();
const {
isOpen: isOpenKbSelect,
onOpen: onOpenKbSelect,
onClose: onCloseKbSelect
} = useDisclosure();
const showKbList = useMemo(
() => allDatasets.filter((item) => activeKbs.find((kb) => kb.kbId === item._id)),
[allDatasets, activeKbs]
);
useQuery(['loadAllDatasets'], loadAllDatasets);
return (
<>
<Grid gridTemplateColumns={'1fr 1fr'} gridGap={4}>
<Button h={'36px'} onClick={onOpenKbSelect}>
</Button>
{showKbList.map((item) => (
<Flex
key={item._id}
alignItems={'center'}
h={'36px'}
border={theme.borders.base}
px={2}
borderRadius={'md'}
>
<Avatar src={item.avatar} w={'24px'}></Avatar>
<Box ml={3} fontWeight={'bold'} fontSize={['md', 'lg', 'xl']}>
{item.name}
</Box>
</Flex>
))}
</Grid>
<DatasetSelectModal
isOpen={isOpenKbSelect}
activeKbs={activeKbs}
onChange={onChange}
onClose={onCloseKbSelect}
/>
</>
);
};
const NodeKbSearch = ({ data }: NodeProps<FlowModuleItemType>) => {
const { moduleId, inputs, outputs } = data;
const { onChangeNode } = useFlowStore();
return (
<NodeCard minW={'400px'} {...data}>
<Divider text="Input" />
<Container>
<RenderInput
moduleId={moduleId}
flowInputList={inputs}
CustomComponent={{
kbList: ({ key, value, ...props }) => (
<KBSelect
activeKbs={value}
onChange={(e) => {
onChangeNode({
moduleId,
key,
type: 'inputs',
value: {
...props,
key,
value: e
}
});
}}
/>
)
}}
/>
<RenderInput moduleId={moduleId} flowInputList={inputs} />
</Container>
<Divider text="Output" />
<Container>

View File

@@ -1,24 +1,18 @@
import React from 'react';
import { NodeProps } from 'reactflow';
import { Box } from '@chakra-ui/react';
import NodeCard from '../modules/NodeCard';
import { FlowModuleItemType } from '@/types/core/app/flow';
import Container from '../modules/Container';
import { SystemInputEnum } from '@/constants/app';
import { FlowValueTypeEnum } from '@/constants/flow';
import SourceHandle from '../render/SourceHandle';
import RenderOutput from '../render/RenderOutput';
const QuestionInputNode = ({ data }: NodeProps<FlowModuleItemType>) => {
const { moduleId, inputs, outputs } = data;
return (
<NodeCard minW={'240px'} {...data}>
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'} textAlign={'end'}>
<Box position={'relative'}>
<SourceHandle
handleKey={SystemInputEnum.userChatInput}
valueType={FlowValueTypeEnum.string}
/>
</Box>
<RenderOutput moduleId={moduleId} flowOutputList={outputs} />
</Container>
</NodeCard>
);

View File

@@ -26,7 +26,7 @@ import React, {
} from 'react';
import { customAlphabet } from 'nanoid';
import { appModule2FlowEdge, appModule2FlowNode } from '@/utils/adapt';
import { useToast } from '@/hooks/useToast';
import { useToast } from '@/web/common/hooks/useToast';
import { FlowModuleTypeEnum, FlowValueTypeEnum } from '@/constants/flow';
import { useTranslation } from 'next-i18next';
import { AppModuleItemType } from '@/types/app';

View File

@@ -3,7 +3,7 @@ import { Box, Flex } from '@chakra-ui/react';
import { ModuleTemplates } from '@/constants/flow/ModuleTemplate';
import { FlowModuleItemType, FlowModuleTemplateType } from '@/types/core/app/flow';
import type { Node } from 'reactflow';
import { useGlobalStore } from '@/store/global';
import { useGlobalStore } from '@/web/common/store/global';
import Avatar from '@/components/Avatar';
import { FlowModuleTypeEnum } from '@/constants/flow';
import { useFlowStore } from './Provider';

View File

@@ -6,8 +6,8 @@ import type { FlowModuleItemType } from '@/types/core/app/flow';
import MyTooltip from '@/components/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { useTranslation } from 'react-i18next';
import { useEditTitle } from '@/hooks/useEditTitle';
import { useToast } from '@/hooks/useToast';
import { useEditTitle } from '@/web/common/hooks/useEditTitle';
import { useToast } from '@/web/common/hooks/useToast';
import { useFlowStore } from '../Provider';
type Props = FlowModuleItemType & {

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useMemo, useState } from 'react';
import type { FlowInputItemType, SelectAppItemType } from '@/types/core/app/flow';
import {
Box,
@@ -12,20 +12,31 @@ import {
Flex,
useDisclosure,
Button,
useTheme
useTheme,
Grid
} from '@chakra-ui/react';
import { FlowInputItemTypeEnum } from '@/constants/flow';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import dynamic from 'next/dynamic';
import { useFlowStore } from '../Provider';
import Avatar from '@/components/Avatar';
import MySelect from '@/components/Select';
import MySlider from '@/components/Slider';
import MyTooltip from '@/components/MyTooltip';
import TargetHandle from './TargetHandle';
import MyIcon from '@/components/Icon';
import { useTranslation } from 'react-i18next';
import { AIChatProps } from '@/types/core/aiChat';
import { chatModelList } from '@/web/common/store/static';
import { formatPrice } from '@fastgpt/common/bill';
import { useDatasetStore } from '@/web/core/store/dataset';
import { SelectedDatasetType } from '@/types/core/dataset';
import { useQuery } from '@tanstack/react-query';
const SetInputFieldModal = dynamic(() => import('../modules/SetInputFieldModal'));
const SelectAppModal = dynamic(() => import('../../../SelectAppModal'));
import { useFlowStore } from '../Provider';
import Avatar from '@/components/Avatar';
const AIChatSettingsModal = dynamic(() => import('../../../AIChatSettingsModal'));
const DatasetSelectModal = dynamic(() => import('../../../DatasetSelectModal'));
export const Label = ({
moduleId,
@@ -145,123 +156,51 @@ const RenderInput = ({
moduleId: string;
CustomComponent?: Record<string, (e: FlowInputItemType) => React.ReactNode>;
}) => {
const { onChangeNode } = useFlowStore();
const sortInputs = useMemo(
() => flowInputList.sort((a, b) => (a.key === FlowInputItemTypeEnum.switch ? -1 : 1)),
[flowInputList]
);
return (
<>
{flowInputList.map(
{sortInputs.map(
(item) =>
item.type !== FlowInputItemTypeEnum.hidden && (
<Box key={item.key} _notLast={{ mb: 7 }} position={'relative'}>
{!!item.label && <Label moduleId={moduleId} inputKey={item.key} {...item} />}
<Box mt={2} className={'nodrag'}>
{item.type === FlowInputItemTypeEnum.numberInput && (
<NumberInput
defaultValue={item.value}
min={item.min}
max={item.max}
onChange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: item.key,
value: {
...item,
value: Number(e)
}
});
}}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<NumberInputRender item={item} moduleId={moduleId} />
)}
{item.type === FlowInputItemTypeEnum.input && (
<Input
placeholder={item.placeholder}
defaultValue={item.value}
onChange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: item.key,
value: {
...item,
value: e.target.value
}
});
}}
/>
<TextInputRender item={item} moduleId={moduleId} />
)}
{item.type === FlowInputItemTypeEnum.textarea && (
<Textarea
rows={5}
placeholder={item.placeholder}
resize={'both'}
defaultValue={item.value}
onChange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: item.key,
value: {
...item,
value: e.target.value
}
});
}}
/>
<TextareaRender item={item} moduleId={moduleId} />
)}
{item.type === FlowInputItemTypeEnum.select && (
<MySelect
width={'100%'}
value={item.value}
list={item.list || []}
onchange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: item.key,
value: {
...item,
value: e
}
});
}}
/>
<SelectRender item={item} moduleId={moduleId} />
)}
{item.type === FlowInputItemTypeEnum.slider && (
<Box pt={5} pb={4} px={2}>
<MySlider
markList={item.markList}
width={'100%'}
min={item.min || 0}
max={item.max}
step={item.step || 1}
value={item.value}
onChange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: item.key,
value: {
...item,
value: e
}
});
}}
/>
</Box>
<SliderRender item={item} moduleId={moduleId} />
)}
{item.type === FlowInputItemTypeEnum.selectApp && (
<SelectAppRender item={item} moduleId={moduleId} />
)}
{item.type === FlowInputItemTypeEnum.quoteList && (
<QuoteListRender inputs={sortInputs} item={item} moduleId={moduleId} />
)}
{item.type === FlowInputItemTypeEnum.maxToken && (
<MaxTokenRender inputs={sortInputs} item={item} moduleId={moduleId} />
)}
{item.type === FlowInputItemTypeEnum.selectChatModel && (
<SelectChatModelRender inputs={sortInputs} item={item} moduleId={moduleId} />
)}
{item.type === FlowInputItemTypeEnum.selectDataset && (
<SelectDatasetRender item={item} moduleId={moduleId} />
)}
{item.type === FlowInputItemTypeEnum.custom && CustomComponent[item.key] && (
<>{CustomComponent[item.key]({ ...item })}</>
)}
{item.type === FlowInputItemTypeEnum.selectApp && (
<RenderSelectApp app={item} moduleId={moduleId} />
)}
</Box>
</Box>
)
@@ -272,7 +211,346 @@ const RenderInput = ({
export default React.memo(RenderInput);
function RenderSelectApp({ app, moduleId }: { app: FlowInputItemType; moduleId: string }) {
type RenderProps = {
inputs?: FlowInputItemType[];
item: FlowInputItemType;
moduleId: string;
};
var NumberInputRender = React.memo(function NumberInputRender({ item, moduleId }: RenderProps) {
const { onChangeNode } = useFlowStore();
return (
<NumberInput
defaultValue={item.value}
min={item.min}
max={item.max}
onChange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: item.key,
value: {
...item,
value: Number(e)
}
});
}}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
);
});
var TextInputRender = React.memo(function TextInputRender({ item, moduleId }: RenderProps) {
const { onChangeNode } = useFlowStore();
return (
<Input
placeholder={item.placeholder}
defaultValue={item.value}
onChange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: item.key,
value: {
...item,
value: e.target.value
}
});
}}
/>
);
});
var TextareaRender = React.memo(function TextareaRender({ item, moduleId }: RenderProps) {
const { onChangeNode } = useFlowStore();
return (
<Textarea
rows={5}
placeholder={item.placeholder}
resize={'both'}
defaultValue={item.value}
onChange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: item.key,
value: {
...item,
value: e.target.value
}
});
}}
/>
);
});
var SelectRender = React.memo(function SelectRender({ item, moduleId }: RenderProps) {
const { onChangeNode } = useFlowStore();
return (
<MySelect
width={'100%'}
value={item.value}
list={item.list || []}
onchange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: item.key,
value: {
...item,
value: e
}
});
}}
/>
);
});
var SliderRender = React.memo(function SliderRender({ item, moduleId }: RenderProps) {
const { onChangeNode } = useFlowStore();
return (
<Box pt={5} pb={4} px={2}>
<MySlider
markList={item.markList}
width={'100%'}
min={item.min || 0}
max={item.max}
step={item.step || 1}
value={item.value}
onChange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: item.key,
value: {
...item,
value: e
}
});
}}
/>
</Box>
);
});
var QuoteListRender = React.memo(function QuoteListRender({ inputs = [], moduleId }: RenderProps) {
const { onChangeNode } = useFlowStore();
const { t } = useTranslation();
const chatModulesData = useMemo(() => {
const obj: Record<string, any> = {};
inputs.forEach((item) => {
obj[item.key] = item.value;
});
return obj as AIChatProps;
}, [inputs]);
const {
isOpen: isOpenAIChatSetting,
onOpen: onOpenAIChatSetting,
onClose: onCloseAIChatSetting
} = useDisclosure();
return (
<>
<Button
variant={'base'}
leftIcon={<MyIcon name={'settingLight'} w={'14px'} />}
onClick={onOpenAIChatSetting}
>
{t('app.Quote Prompt Settings')}
</Button>
{isOpenAIChatSetting && (
<AIChatSettingsModal
onClose={onCloseAIChatSetting}
onSuccess={(e) => {
for (let key in e) {
const item = inputs.find((input) => input.key === key);
if (!item) continue;
onChangeNode({
moduleId,
type: 'inputs',
key,
value: {
...item,
//@ts-ignore
value: e[key]
}
});
}
onCloseAIChatSetting();
}}
defaultData={chatModulesData}
/>
)}
</>
);
});
var MaxTokenRender = React.memo(function MaxTokenRender({
inputs = [],
item,
moduleId
}: RenderProps) {
const { onChangeNode } = useFlowStore();
const model = inputs.find((item) => item.key === 'model')?.value;
const modelData = chatModelList.find((item) => item.model === model);
const maxToken = modelData ? modelData.contextMaxToken : 4000;
const markList = [
{ label: '100', value: 100 },
{ label: `${maxToken}`, value: maxToken }
];
return (
<Box pt={5} pb={4} px={2}>
<MySlider
markList={markList}
width={'100%'}
min={item.min || 100}
max={maxToken}
step={item.step || 1}
value={item.value}
onChange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: item.key,
value: {
...item,
value: e
}
});
}}
/>
</Box>
);
});
var SelectChatModelRender = React.memo(function SelectChatModelRender({
inputs = [],
item,
moduleId
}: RenderProps) {
const { onChangeNode } = useFlowStore();
const list = chatModelList.map((item) => {
const priceStr = `(${formatPrice(item.price, 1000)}元/1k Tokens)`;
return {
value: item.model,
label: `${item.name}${priceStr}`
};
});
return (
<MySelect
width={'100%'}
value={item.value}
list={list}
onchange={(e) => {
onChangeNode({
moduleId,
type: 'inputs',
key: item.key,
value: {
...item,
value: e
}
});
// update max tokens
const model = chatModelList.find((item) => item.model === e) || chatModelList[0];
if (!model) return;
onChangeNode({
moduleId,
type: 'inputs',
key: 'maxToken',
value: {
...inputs.find((input) => input.key === 'maxToken'),
markList: [
{ label: '100', value: 100 },
{ label: `${model.contextMaxToken}`, value: model.contextMaxToken }
],
max: model.contextMaxToken,
value: model.contextMaxToken / 2
}
});
}}
/>
);
});
var SelectDatasetRender = React.memo(function SelectDatasetRender({ item, moduleId }: RenderProps) {
const { onChangeNode } = useFlowStore();
const theme = useTheme();
const { allDatasets, loadAllDatasets } = useDatasetStore();
const {
isOpen: isOpenKbSelect,
onOpen: onOpenKbSelect,
onClose: onCloseKbSelect
} = useDisclosure();
const showKbList = useMemo(() => {
const value = item.value as SelectedDatasetType;
return allDatasets.filter((dataset) => value.find((kb) => kb.kbId === dataset._id));
}, [allDatasets, item.value]);
useQuery(['loadAllDatasets'], loadAllDatasets);
return (
<>
<Grid gridTemplateColumns={'1fr 1fr'} gridGap={4}>
<Button h={'36px'} onClick={onOpenKbSelect}>
</Button>
{showKbList.map((item) => (
<Flex
key={item._id}
alignItems={'center'}
h={'36px'}
border={theme.borders.base}
px={2}
borderRadius={'md'}
>
<Avatar src={item.avatar} w={'24px'}></Avatar>
<Box ml={3} fontWeight={'bold'} fontSize={['md', 'lg', 'xl']}>
{item.name}
</Box>
</Flex>
))}
</Grid>
<DatasetSelectModal
isOpen={isOpenKbSelect}
activeKbs={item.value}
onChange={(e) => {
onChangeNode({
moduleId,
key: item.key,
type: 'inputs',
value: {
...item,
value: e
}
});
}}
onClose={onCloseKbSelect}
/>
</>
);
});
var SelectAppRender = React.memo(function SelectAppRender({ item, moduleId }: RenderProps) {
const { onChangeNode, appId } = useFlowStore();
const theme = useTheme();
@@ -282,7 +560,7 @@ function RenderSelectApp({ app, moduleId }: { app: FlowInputItemType; moduleId:
onClose: onCloseSelectApp
} = useDisclosure();
const value = app.value as SelectAppItemType | undefined;
const value = item.value as SelectAppItemType | undefined;
return (
<>
@@ -303,7 +581,7 @@ function RenderSelectApp({ app, moduleId }: { app: FlowInputItemType; moduleId:
{isOpenSelectApp && (
<SelectAppModal
defaultApps={app.value?.id ? [app.value.id] : []}
defaultApps={item.value?.id ? [item.value.id] : []}
filterApps={[appId]}
onClose={onCloseSelectApp}
onSuccess={(e) => {
@@ -312,7 +590,7 @@ function RenderSelectApp({ app, moduleId }: { app: FlowInputItemType; moduleId:
type: 'inputs',
key: 'app',
value: {
...app,
...item,
value: e[0]
}
});
@@ -321,4 +599,4 @@ function RenderSelectApp({ app, moduleId }: { app: FlowInputItemType; moduleId:
)}
</>
);
}
});

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useMemo, useState } from 'react';
import type { FlowOutputItemType } from '@/types/core/app/flow';
import { Box, Flex } from '@chakra-ui/react';
import { FlowOutputItemTypeEnum } from '@/constants/flow';
@@ -9,6 +9,7 @@ import MyIcon from '@/components/Icon';
import dynamic from 'next/dynamic';
const SetOutputFieldModal = dynamic(() => import('../modules/SetOutputFieldModal'));
import { useFlowStore } from '../Provider';
import { SystemOutputEnum } from '@/constants/app';
const Label = ({
moduleId,
@@ -127,13 +128,17 @@ const RenderOutput = ({
moduleId: string;
flowOutputList: FlowOutputItemType[];
}) => {
const sortOutput = useMemo(
() => flowOutputList.sort((a, b) => (a.key === SystemOutputEnum.finish ? -1 : 1)),
[flowOutputList]
);
return (
<>
{flowOutputList.map(
{sortOutput.map(
(item) =>
item.type !== FlowOutputItemTypeEnum.hidden && (
<Box key={item.key} _notLast={{ mb: 7 }} position={'relative'}>
<Label moduleId={moduleId} outputKey={item.key} outputs={flowOutputList} {...item} />
<Label moduleId={moduleId} outputKey={item.key} outputs={sortOutput} {...item} />
<Box mt={FlowOutputItemTypeEnum.answer ? 0 : 2} className={'nodrag'}>
{item.type === FlowOutputItemTypeEnum.source && (
<SourceHandle handleKey={item.key} valueType={item.valueType} />

View File

@@ -10,11 +10,11 @@ import {
} from '@/constants/flow';
import { FlowOutputTargetItemType } from '@/types/core/app/flow';
import { AppModuleItemType } from '@/types/app';
import { useRequest } from '@/hooks/useRequest';
import { useRequest } from '@/web/common/hooks/useRequest';
import type { AppSchema } from '@/types/mongoSchema';
import { useUserStore } from '@/store/user';
import { useUserStore } from '@/web/support/store/user';
import { useTranslation } from 'next-i18next';
import { useCopyData } from '@/hooks/useCopyData';
import { useCopyData } from '@/web/common/hooks/useCopyData';
import dynamic from 'next/dynamic';
import styles from './index.module.scss';
import { AppTypeEnum } from '@/constants/app';
@@ -125,6 +125,9 @@ function FlowHeader({ app, onCloseSettings }: Props & {}) {
if (item.inputs.find((input) => input.required && !input.connected)) {
return Promise.reject(`${item.name}】存在未连接的必填输入`);
}
if (item.inputs.find((input) => input.valueCheck && !input.valueCheck(input.value))) {
return Promise.reject(`${item.name}】存在为填写的必填项`);
}
}
return updateAppDetail(app._id, {

View File

@@ -19,18 +19,18 @@ import {
Text,
Switch
} from '@chakra-ui/react';
import { useUserStore } from '@/store/user';
import { useUserStore } from '@/web/support/store/user';
import { useQuery } from '@tanstack/react-query';
import { QuestionOutlineIcon, SmallAddIcon } from '@chakra-ui/icons';
import { useForm, useFieldArray } from 'react-hook-form';
import { useGlobalStore } from '@/store/global';
import { useGlobalStore } from '@/web/common/store/global';
import {
appModules2Form,
getDefaultAppForm,
appForm2Modules,
type EditFormType
} from '@/utils/app';
import { chatModelList } from '@/store/static';
import { chatModelList } from '@/web/common/store/static';
import { formatPrice } from '@fastgpt/common/bill/index';
import {
ChatModelSystemTip,
@@ -39,14 +39,14 @@ import {
questionGuideTip
} from '@/constants/flow/ModuleTemplate';
import { AppModuleItemType, VariableItemType } from '@/types/app';
import { useRequest } from '@/hooks/useRequest';
import { useConfirm } from '@/hooks/useConfirm';
import { useRequest } from '@/web/common/hooks/useRequest';
import { useConfirm } from '@/web/common/hooks/useConfirm';
import { FlowModuleTypeEnum } from '@/constants/flow';
import { streamFetch } from '@/api/fetch';
import { streamFetch } from '@/web/common/api/fetch';
import { useRouter } from 'next/router';
import { useToast } from '@/hooks/useToast';
import { useToast } from '@/web/common/hooks/useToast';
import { AppSchema } from '@/types/mongoSchema';
import { delModelById } from '@/api/app';
import { delModelById } from '@/web/core/api/app';
import { useTranslation } from 'react-i18next';
import { getGuideModule } from '@/components/ChatBox/utils';
@@ -61,7 +61,7 @@ import ChatBox, { type ComponentRef, type StartChatFnProps } from '@/components/
import { addVariable } from '../VariableEditModal';
import { KbParamsModal } from '../DatasetSelectModal';
import { AppTypeEnum } from '@/constants/app';
import { useDatasetStore } from '@/store/dataset';
import { useDatasetStore } from '@/web/core/store/dataset';
const VariableEditModal = dynamic(() => import('../VariableEditModal'));
const InfoModal = dynamic(() => import('../InfoModal'));

View File

@@ -1,7 +1,7 @@
import React, { useEffect, useMemo, useRef } from 'react';
import * as echarts from 'echarts';
import { useGlobalStore } from '@/store/global';
import { getAppTotalUsage } from '@/api/app';
import { useGlobalStore } from '@/web/common/store/global';
import { getAppTotalUsage } from '@/web/core/api/app';
import { useQuery } from '@tanstack/react-query';
import dayjs from 'dayjs';
import { formatPrice } from '@fastgpt/common/bill/index';

View File

@@ -15,7 +15,7 @@ import Avatar from '@/components/Avatar';
import { useForm } from 'react-hook-form';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import type { SelectedDatasetType } from '@/types/core/dataset';
import { useToast } from '@/hooks/useToast';
import { useToast } from '@/web/common/hooks/useToast';
import MySlider from '@/components/Slider';
import MyTooltip from '@/components/MyTooltip';
import MyModal from '@/components/MyModal';
@@ -23,8 +23,8 @@ import MyIcon from '@/components/Icon';
import { KbTypeEnum } from '@/constants/dataset';
import { useTranslation } from 'react-i18next';
import { useQuery } from '@tanstack/react-query';
import { useDatasetStore } from '@/store/dataset';
import { feConfigs } from '@/store/static';
import { useDatasetStore } from '@/web/core/store/dataset';
import { feConfigs } from '@/web/common/store/static';
import DatasetSelectContainer, { useDatasetSelect } from '@/components/core/dataset/SelectModal';
export type KbParamsType = {
@@ -178,7 +178,7 @@ export const DatasetSelectModal = ({
</Grid>
{filterKbList.unSelected.length === 0 && (
<Flex mt={5} flexDirection={'column'} alignItems={'center'}>
<MyIcon name="empty" w={'48px'} h={'48px'} color={'transparent'} />
<MyIcon name="empty" w={'48px'} h={'48px'} mt={'20vh'} color={'transparent'} />
<Box mt={2} color={'myGray.500'}>
西~
</Box>

View File

@@ -11,12 +11,12 @@ import {
} from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { AppSchema } from '@/types/mongoSchema';
import { useToast } from '@/hooks/useToast';
import { useSelectFile } from '@/hooks/useSelectFile';
import { compressImg } from '@/utils/web/file';
import { useToast } from '@/web/common/hooks/useToast';
import { useSelectFile } from '@/web/common/hooks/useSelectFile';
import { compressImg } from '@/web/common/utils/file';
import { getErrText } from '@/utils/tools';
import { useUserStore } from '@/store/user';
import { useRequest } from '@/hooks/useRequest';
import { useUserStore } from '@/web/support/store/user';
import { useRequest } from '@/web/common/hooks/useRequest';
import Avatar from '@/components/Avatar';
import MyModal from '@/components/MyModal';

Some files were not shown because too many files have changed in this diff Show More