mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-21 11:43:56 +00:00
Optimize the project structure and introduce DDD design (#394)
This commit is contained in:
@@ -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",
|
||||
|
@@ -242,7 +242,7 @@
|
||||
"openapi": {
|
||||
"app key tips": "这些 key 已有当前应用标识,具体使用可参考文档",
|
||||
"key alias": "key 的别名,仅用于展示",
|
||||
"key tips": "你可以使用 API 秘钥访问一些特定的接口"
|
||||
"key tips": "你可以使用 API 秘钥访问一些特定的接口(无法访问应用,访问应用需使用应用内的API Key)"
|
||||
},
|
||||
"outlink": {
|
||||
"Copy Iframe": "嵌入网页",
|
||||
|
@@ -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);
|
@@ -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 });
|
28
projects/app/src/api/core/dataset/data.d.ts
vendored
28
projects/app/src/api/core/dataset/data.d.ts
vendored
@@ -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;
|
||||
};
|
@@ -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}`);
|
10
projects/app/src/api/core/dataset/file.d.ts
vendored
10
projects/app/src/api/core/dataset/file.d.ts
vendored
@@ -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[] };
|
@@ -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);
|
34
projects/app/src/api/core/dataset/index.d.ts
vendored
34
projects/app/src/api/core/dataset/index.d.ts
vendored
@@ -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'];
|
@@ -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);
|
@@ -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 });
|
@@ -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 });
|
@@ -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');
|
@@ -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,
|
||||
|
@@ -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';
|
||||
|
@@ -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,
|
||||
|
@@ -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';
|
||||
|
@@ -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';
|
||||
|
@@ -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]);
|
||||
|
@@ -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';
|
||||
|
@@ -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 } = {
|
||||
|
@@ -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,
|
||||
|
@@ -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 {
|
||||
|
@@ -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';
|
||||
|
@@ -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-]': {
|
||||
|
@@ -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}
|
||||
|
@@ -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 = {
|
||||
|
@@ -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;
|
||||
|
@@ -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';
|
||||
|
||||
|
@@ -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 };
|
||||
|
@@ -7,6 +7,9 @@ export enum SystemInputEnum {
|
||||
'userChatInput' = 'userChatInput',
|
||||
'questionGuide' = 'questionGuide'
|
||||
}
|
||||
export enum SystemOutputEnum {
|
||||
finish = 'finish'
|
||||
}
|
||||
|
||||
export enum VariableInputEnum {
|
||||
input = 'input',
|
||||
|
@@ -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
|
||||
]
|
||||
};
|
||||
|
||||
|
@@ -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'
|
||||
}
|
||||
|
||||
|
12
projects/app/src/constants/flow/outputTemplate.ts
Normal file
12
projects/app/src/constants/flow/outputTemplate.ts
Normal 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: []
|
||||
};
|
14
projects/app/src/global/common/api/systemRes.d.ts
vendored
Normal file
14
projects/app/src/global/common/api/systemRes.d.ts
vendored
Normal 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;
|
||||
};
|
@@ -1,6 +1,6 @@
|
||||
import { ChatCompletionRequestMessage } from '@fastgpt/core/ai/type';
|
||||
|
||||
export type CreateQuestionGuideProps = {
|
||||
export type CreateQuestionGuideParams = {
|
||||
messages: ChatCompletionRequestMessage[];
|
||||
shareId?: string;
|
||||
};
|
@@ -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'];
|
||||
}
|
||||
};
|
59
projects/app/src/global/core/api/datasetReq.d.ts
vendored
Normal file
59
projects/app/src/global/core/api/datasetReq.d.ts
vendored
Normal 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;
|
||||
};
|
15
projects/app/src/global/core/api/datasetRes.d.ts
vendored
Normal file
15
projects/app/src/global/core/api/datasetRes.d.ts
vendored
Normal 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;
|
||||
};
|
6
projects/app/src/global/support/api/outLinkRes.d.ts
vendored
Normal file
6
projects/app/src/global/support/api/outLinkRes.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { InitChatResponse } from '@/global/core/api/chatRes.d';
|
||||
|
||||
export type InitShareChatResponse = {
|
||||
userAvatar: string;
|
||||
app: InitChatResponse['app'];
|
||||
};
|
@@ -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.
|
||||
|
@@ -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';
|
||||
|
||||
|
@@ -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'));
|
||||
|
||||
|
@@ -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';
|
||||
|
@@ -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 = () => {
|
||||
|
@@ -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>
|
||||
|
@@ -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();
|
||||
|
@@ -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 = () => {
|
||||
|
@@ -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';
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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';
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -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';
|
||||
|
||||
/* 初始化我的聊天框,需要身份验证 */
|
||||
|
@@ -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';
|
||||
|
@@ -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 {
|
||||
|
@@ -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,
|
||||
|
@@ -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 {
|
||||
|
@@ -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 = {
|
||||
|
@@ -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('缺少参数');
|
||||
|
@@ -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>) {
|
||||
|
@@ -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';
|
||||
|
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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[];
|
||||
|
@@ -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';
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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';
|
||||
|
@@ -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, {
|
@@ -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) {
|
||||
|
@@ -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,
|
||||
|
@@ -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';
|
||||
|
||||
|
@@ -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 }) => {
|
||||
|
@@ -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>
|
||||
);
|
||||
};
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
);
|
||||
|
@@ -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';
|
||||
|
@@ -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';
|
||||
|
@@ -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 & {
|
||||
|
@@ -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:
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@@ -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} />
|
||||
|
@@ -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, {
|
||||
|
@@ -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'));
|
||||
|
@@ -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';
|
||||
|
@@ -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>
|
||||
|
@@ -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
Reference in New Issue
Block a user