mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-30 18:48:55 +00:00
4.6.7-alpha commit (#743)
Co-authored-by: Archer <545436317@qq.com> Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
@@ -56,7 +56,7 @@ const FeedbackModal = ({
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button variant={'whiteBase'} mr={2} onClick={onClose}>
|
||||
{t('Cancel')}
|
||||
{t('common.Close')}
|
||||
</Button>
|
||||
<Button isLoading={isLoading} onClick={mutate}>
|
||||
{t('core.chat.Feedback Submit')}
|
||||
|
@@ -12,6 +12,7 @@ import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils';
|
||||
import ChatBoxDivider from '@/components/core/chat/Divider';
|
||||
import { strIsLink } from '@fastgpt/global/common/string/tools';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
|
||||
const QuoteModal = dynamic(() => import('./QuoteModal'), { ssr: false });
|
||||
const ContextModal = dynamic(() => import('./ContextModal'), { ssr: false });
|
||||
@@ -123,7 +124,7 @@ const ResponseTags = ({
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Image src={item.icon} alt={''} mr={1} flexShrink={0} w={'12px'} />
|
||||
<MyIcon name={item.icon as any} mr={1} flexShrink={0} w={'12px'} />
|
||||
<Box className="textEllipsis3" wordBreak={'break-all'} flex={'1 0 0'}>
|
||||
{item.sourceName}
|
||||
</Box>
|
||||
|
@@ -3,7 +3,7 @@ import { ModalBody, useTheme, ModalFooter, Button, Box, Card, Flex, Grid } from
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import Avatar from '../Avatar';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import DatasetSelectModal, { useDatasetSelect } from '@/components/core/dataset/SelectModal';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { AdminFbkType } from '@fastgpt/global/core/chat/type.d';
|
||||
@@ -46,7 +46,7 @@ const SelectMarkCollection = ({
|
||||
paths={paths}
|
||||
onClose={onClose}
|
||||
setParentId={setParentId}
|
||||
tips={t('core.chat.Select Mark Kb Desc')}
|
||||
tips={t('core.chat.Select dataset Desc')}
|
||||
>
|
||||
<ModalBody flex={'1 0 0'} overflowY={'auto'}>
|
||||
<Grid
|
||||
|
@@ -11,7 +11,7 @@ import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import Markdown from '../Markdown';
|
||||
import { QuoteList } from './QuoteModal';
|
||||
import { DatasetSearchModeMap } from '@fastgpt/global/core/dataset/constant';
|
||||
import { DatasetSearchModeMap } from '@fastgpt/global/core/dataset/constants';
|
||||
|
||||
function Row({
|
||||
label,
|
||||
@@ -141,6 +141,7 @@ const ResponseBox = React.memo(function ResponseBox({
|
||||
value={`${activeModule?.runningTime || 0}s`}
|
||||
/>
|
||||
<Row label={t('core.chat.response.module model')} value={activeModule?.model} />
|
||||
<Row label={t('wallet.bill.Chars length')} value={`${activeModule?.charsLength}`} />
|
||||
<Row label={t('wallet.bill.Input Token Length')} value={`${activeModule?.inputTokens}`} />
|
||||
<Row label={t('wallet.bill.Output Token Length')} value={`${activeModule?.outputTokens}`} />
|
||||
<Row label={t('core.chat.response.module query')} value={activeModule?.query} />
|
||||
|
@@ -174,7 +174,7 @@ const Navbar = ({ unread }: { unread: number }) => {
|
||||
mb={0}
|
||||
color={'myGray.500'}
|
||||
>
|
||||
<MyIcon name={'common/courseLight'} width={'26px'} height={'26px'} />
|
||||
<MyIcon name={'common/courseLight'} width={'24px'} height={'24px'} />
|
||||
</Link>
|
||||
</MyTooltip>
|
||||
)}
|
||||
@@ -189,7 +189,7 @@ const Navbar = ({ unread }: { unread: number }) => {
|
||||
mt={0}
|
||||
color={'myGray.500'}
|
||||
>
|
||||
<MyIcon name={'common/gitLight'} width={'22px'} height={'22px'} />
|
||||
<MyIcon name={'common/gitInlight'} width={'26px'} height={'26px'} />
|
||||
</Link>
|
||||
</MyTooltip>
|
||||
)}
|
||||
|
@@ -15,6 +15,7 @@ const NavbarPhone = ({ unread }: { unread: number }) => {
|
||||
{
|
||||
label: t('navbar.Chat'),
|
||||
icon: 'core/chat/chatLight',
|
||||
activeIcon: 'core/chat/chatFill',
|
||||
link: `/chat?appId=${lastChatAppId}&chatId=${lastChatId}`,
|
||||
activeLink: ['/chat'],
|
||||
unread: 0
|
||||
@@ -22,20 +23,23 @@ const NavbarPhone = ({ unread }: { unread: number }) => {
|
||||
{
|
||||
label: t('navbar.Apps'),
|
||||
icon: 'core/app/aiLight',
|
||||
activeIcon: 'core/app/aiFill',
|
||||
link: `/app/list`,
|
||||
activeLink: ['/app/list', '/app/detail'],
|
||||
unread: 0
|
||||
},
|
||||
{
|
||||
label: t('navbar.Tools'),
|
||||
icon: 'phoneTabbar/more',
|
||||
icon: 'phoneTabbar/tool',
|
||||
activeIcon: 'phoneTabbar/toolFill',
|
||||
link: '/tools',
|
||||
activeLink: ['/tools'],
|
||||
unread: 0
|
||||
},
|
||||
{
|
||||
label: t('navbar.Account'),
|
||||
icon: 'phoneTabbar/me',
|
||||
icon: 'support/user/userLight',
|
||||
activeIcon: 'support/user/userFill',
|
||||
link: '/account',
|
||||
activeLink: ['/account'],
|
||||
unread
|
||||
@@ -68,35 +72,24 @@ const NavbarPhone = ({ unread }: { unread: number }) => {
|
||||
transform={'scale(0.9)'}
|
||||
{...(item.activeLink.includes(router.pathname)
|
||||
? {
|
||||
color: '#7089f1'
|
||||
color: 'primary.600'
|
||||
}
|
||||
: {
|
||||
color: 'myGray.500'
|
||||
})}
|
||||
_after={
|
||||
item.activeLink.includes(router.pathname)
|
||||
? {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%,-50%)',
|
||||
borderRadius: '50%',
|
||||
w: '18px',
|
||||
h: '18px',
|
||||
bg: ' #6782f1',
|
||||
filter: 'blur(10px)',
|
||||
boxShadow: '0px 2px 4px 0px rgba(0, 0, 0, 0.25)'
|
||||
}
|
||||
: {}
|
||||
}
|
||||
onClick={() => {
|
||||
if (item.link === router.asPath) return;
|
||||
router.push(item.link);
|
||||
}}
|
||||
>
|
||||
<Badge isDot count={item.unread}>
|
||||
<MyIcon name={item.icon as any} width={'20px'} height={'20px'} />
|
||||
<MyIcon
|
||||
name={
|
||||
(item.activeLink.includes(router.pathname) ? item.activeIcon : item.icon) as any
|
||||
}
|
||||
width={'20px'}
|
||||
height={'20px'}
|
||||
/>
|
||||
<Box fontSize={'12px'}>{item.label}</Box>
|
||||
</Badge>
|
||||
</Flex>
|
||||
|
@@ -17,6 +17,7 @@ const Loading = ({
|
||||
position={fixed ? 'fixed' : 'absolute'}
|
||||
zIndex={zIndex}
|
||||
bg={bg}
|
||||
borderRadius={'md'}
|
||||
top={0}
|
||||
left={0}
|
||||
right={0}
|
||||
|
@@ -19,8 +19,8 @@ const MyMenu = ({ width, offset = [0, 10], Button, menuList }: Props) => {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
_hover: {
|
||||
backgroundColor: 'myWhite.600',
|
||||
color: 'hover.blue'
|
||||
backgroundColor: 'myGray.05',
|
||||
color: 'primary.600'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -41,7 +41,7 @@ const MyMenu = ({ width, offset = [0, 10], Button, menuList }: Props) => {
|
||||
e.stopPropagation();
|
||||
item.onClick && item.onClick();
|
||||
}}
|
||||
color={item.isActive ? 'primary.500' : ''}
|
||||
color={item.isActive ? 'primary.700' : 'myGray.600'}
|
||||
whiteSpace={'pre-wrap'}
|
||||
>
|
||||
{item.child}
|
||||
|
@@ -1,16 +1,7 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalCloseButton,
|
||||
ModalContentProps,
|
||||
Box,
|
||||
Image
|
||||
} from '@chakra-ui/react';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { ModalContentProps } from '@chakra-ui/react';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import CustomModal from '@fastgpt/web/components/common/MyModal';
|
||||
|
||||
export interface MyModalProps extends ModalContentProps {
|
||||
iconSrc?: string;
|
||||
@@ -33,59 +24,18 @@ const MyModal = ({
|
||||
}: MyModalProps) => {
|
||||
const { isPc } = useSystemStore();
|
||||
return (
|
||||
<Modal
|
||||
<CustomModal
|
||||
isOpen={isOpen}
|
||||
onClose={() => onClose && onClose()}
|
||||
autoFocus={false}
|
||||
onClose={onClose}
|
||||
iconSrc={iconSrc}
|
||||
title={title}
|
||||
isCentered={isPc ? isCentered : true}
|
||||
w={w}
|
||||
maxW={maxW}
|
||||
{...props}
|
||||
>
|
||||
<ModalOverlay />
|
||||
<ModalContent
|
||||
w={w}
|
||||
minW={['90vw', '400px']}
|
||||
maxW={maxW}
|
||||
position={'relative'}
|
||||
maxH={'85vh'}
|
||||
{...props}
|
||||
>
|
||||
{!title && onClose && <ModalCloseButton zIndex={1} />}
|
||||
{!!title && (
|
||||
<ModalHeader
|
||||
display={'flex'}
|
||||
alignItems={'center'}
|
||||
fontWeight={500}
|
||||
background={'#FBFBFC'}
|
||||
borderBottom={'1px solid #F4F6F8'}
|
||||
roundedTop={'lg'}
|
||||
py={'10px'}
|
||||
>
|
||||
{iconSrc && (
|
||||
<>
|
||||
{iconSrc.startsWith('/') ? (
|
||||
<Image mr={3} objectFit={'contain'} alt="" src={iconSrc} w={'20px'} />
|
||||
) : (
|
||||
<MyIcon mr={3} name={iconSrc as any} w={'20px'} />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{title}
|
||||
<Box flex={1} />
|
||||
{onClose && (
|
||||
<ModalCloseButton position={'relative'} fontSize={'sm'} top={0} right={0} />
|
||||
)}
|
||||
</ModalHeader>
|
||||
)}
|
||||
|
||||
<Box
|
||||
overflow={props.overflow || 'overlay'}
|
||||
h={'100%'}
|
||||
display={'flex'}
|
||||
flexDirection={'column'}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
{children}
|
||||
</CustomModal>
|
||||
);
|
||||
};
|
||||
|
||||
|
@@ -25,9 +25,9 @@ const Tag = ({ children, colorSchema = 'blue', ...props }: Props) => {
|
||||
color: '#A558C9'
|
||||
},
|
||||
gray: {
|
||||
borderColor: '#979797',
|
||||
bg: '#F7F7F7',
|
||||
color: '#979797'
|
||||
borderColor: 'borderColor.base',
|
||||
bg: 'myGray.50',
|
||||
color: 'myGray.700'
|
||||
}
|
||||
};
|
||||
return map[colorSchema];
|
||||
@@ -35,14 +35,14 @@ const Tag = ({ children, colorSchema = 'blue', ...props }: Props) => {
|
||||
|
||||
return (
|
||||
<Flex
|
||||
border={'1px solid'}
|
||||
{...theme}
|
||||
borderWidth={'1px'}
|
||||
px={2}
|
||||
lineHeight={1}
|
||||
py={1}
|
||||
borderRadius={'sm'}
|
||||
fontSize={'xs'}
|
||||
alignItems={'center'}
|
||||
{...theme}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
|
@@ -87,7 +87,7 @@ const MyRadio = ({
|
||||
<Box pr={hiddenCircle ? 0 : 2} color={'myGray.800'}>
|
||||
<Box>{typeof item.title === 'string' ? t(item.title) : item.title}</Box>
|
||||
{!!item.desc && (
|
||||
<Box fontSize={['xs', 'sm']} color={'myGray.500'}>
|
||||
<Box fontSize={'xs'} color={'myGray.500'} lineHeight={1.2}>
|
||||
{t(item.desc)}
|
||||
</Box>
|
||||
)}
|
||||
|
@@ -0,0 +1,95 @@
|
||||
import React, { useRef } from 'react';
|
||||
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
ModalBody,
|
||||
ModalFooter,
|
||||
Textarea,
|
||||
TextareaProps,
|
||||
useDisclosure
|
||||
} from '@chakra-ui/react';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyModal from '@/components/MyModal';
|
||||
|
||||
type Props = TextareaProps & {
|
||||
title?: string;
|
||||
// variables: string[];
|
||||
};
|
||||
|
||||
const MyTextarea = React.forwardRef<HTMLTextAreaElement, Props>(function MyTextarea(props, ref) {
|
||||
const ModalTextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const TextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
const { t } = useTranslation();
|
||||
const { title = t('core.app.edit.Prompt Editor'), ...childProps } = props;
|
||||
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Editor textareaRef={TextareaRef} {...childProps} onOpenModal={onOpen} />
|
||||
{isOpen && (
|
||||
<MyModal iconSrc="/imgs/modal/edit.svg" title={title} isOpen onClose={onClose}>
|
||||
<ModalBody>
|
||||
<Editor
|
||||
textareaRef={ModalTextareaRef}
|
||||
{...childProps}
|
||||
minH={'300px'}
|
||||
maxH={'auto'}
|
||||
minW={['100%', '512px']}
|
||||
/>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (ModalTextareaRef.current && TextareaRef.current) {
|
||||
TextareaRef.current.value = ModalTextareaRef.current.value;
|
||||
}
|
||||
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
{t('common.Confirm')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</MyModal>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
export default React.memo(MyTextarea);
|
||||
|
||||
const Editor = React.memo(function Editor({
|
||||
onOpenModal,
|
||||
textareaRef,
|
||||
...props
|
||||
}: Props & {
|
||||
textareaRef: React.RefObject<HTMLTextAreaElement>;
|
||||
onOpenModal?: () => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Box h={'100%'} w={'100%'} position={'relative'}>
|
||||
<Textarea ref={textareaRef} maxW={'100%'} {...props} />
|
||||
{onOpenModal && (
|
||||
<Box
|
||||
zIndex={1}
|
||||
position={'absolute'}
|
||||
bottom={1}
|
||||
right={2}
|
||||
cursor={'pointer'}
|
||||
onClick={onOpenModal}
|
||||
>
|
||||
<MyTooltip label={t('common.ui.textarea.Magnifying')}>
|
||||
<MyIcon name={'common/fullScreenLight'} w={'14px'} color={'myGray.600'} />
|
||||
</MyTooltip>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
});
|
@@ -1,97 +0,0 @@
|
||||
import React, { useRef } from 'react';
|
||||
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
ModalBody,
|
||||
ModalFooter,
|
||||
Textarea,
|
||||
TextareaProps,
|
||||
useDisclosure
|
||||
} from '@chakra-ui/react';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyModal from '@/components/MyModal';
|
||||
|
||||
type Props = TextareaProps & {
|
||||
title?: string;
|
||||
// variables: string[];
|
||||
};
|
||||
|
||||
const PromptTextarea = React.forwardRef<HTMLTextAreaElement, Props>(
|
||||
function PromptTextarea(props, ref) {
|
||||
const ModalTextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const TextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
const { t } = useTranslation();
|
||||
const { title = t('core.app.edit.Prompt Editor'), ...childProps } = props;
|
||||
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Editor textareaRef={TextareaRef} {...childProps} onOpenModal={onOpen} />
|
||||
{isOpen && (
|
||||
<MyModal iconSrc="/imgs/modal/edit.svg" title={title} isOpen onClose={onClose}>
|
||||
<ModalBody>
|
||||
<Editor
|
||||
textareaRef={ModalTextareaRef}
|
||||
{...childProps}
|
||||
minH={'300px'}
|
||||
maxH={'auto'}
|
||||
minW={['100%', '512px']}
|
||||
/>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (ModalTextareaRef.current && TextareaRef.current) {
|
||||
TextareaRef.current.value = ModalTextareaRef.current.value;
|
||||
}
|
||||
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
{t('common.Confirm')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</MyModal>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default React.memo(PromptTextarea);
|
||||
|
||||
const Editor = React.memo(function Editor({
|
||||
onOpenModal,
|
||||
textareaRef,
|
||||
...props
|
||||
}: Props & {
|
||||
textareaRef: React.RefObject<HTMLTextAreaElement>;
|
||||
onOpenModal?: () => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Box h={'100%'} w={'100%'} position={'relative'}>
|
||||
<Textarea ref={textareaRef} maxW={'100%'} {...props} />
|
||||
{onOpenModal && (
|
||||
<Box
|
||||
zIndex={1}
|
||||
position={'absolute'}
|
||||
bottom={1}
|
||||
right={2}
|
||||
cursor={'pointer'}
|
||||
onClick={onOpenModal}
|
||||
>
|
||||
<MyTooltip label={t('common.ui.textarea.Magnifying')}>
|
||||
<MyIcon name={'common/fullScreenLight'} w={'14px'} color={'myGray.600'} />
|
||||
</MyTooltip>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
});
|
@@ -1,9 +1,9 @@
|
||||
import { Box, Flex, FlexProps } from '@chakra-ui/react';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import React from 'react';
|
||||
import { DatasetTypeMap } from '@fastgpt/global/core/dataset/constant';
|
||||
import { DatasetTypeMap } from '@fastgpt/global/core/dataset/constants';
|
||||
|
||||
const DatasetTypeTag = ({ type, ...props }: { type: `${DatasetTypeEnum}` } & FlexProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
@@ -8,7 +8,7 @@ import { useTranslation } from 'next-i18next';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import dynamic from 'next/dynamic';
|
||||
import MyBox from '@/components/common/MyBox';
|
||||
import { SearchScoreTypeEnum, SearchScoreTypeMap } from '@fastgpt/global/core/dataset/constant';
|
||||
import { SearchScoreTypeEnum, SearchScoreTypeMap } from '@fastgpt/global/core/dataset/constants';
|
||||
|
||||
const InputDataModal = dynamic(() => import('@/pages/dataset/detail/components/InputDataModal'));
|
||||
|
||||
@@ -102,6 +102,7 @@ const QuoteItem = ({
|
||||
overflow={'hidden'}
|
||||
fontSize={'sm'}
|
||||
whiteSpace={'pre-wrap'}
|
||||
wordBreak={'break-all'}
|
||||
_hover={{ '& .hover-data': { display: 'flex' } }}
|
||||
h={'100%'}
|
||||
display={'flex'}
|
||||
@@ -220,7 +221,6 @@ const QuoteItem = ({
|
||||
display={['flex', 'none']}
|
||||
alignItems={'center'}
|
||||
justifyContent={'center'}
|
||||
boxShadow={'-10px 0 10px rgba(255,255,255,1)'}
|
||||
>
|
||||
<MyIcon
|
||||
name={'edit'}
|
||||
|
@@ -7,6 +7,7 @@ import { useTranslation } from 'next-i18next';
|
||||
import { getFileAndOpen } from '@/web/core/dataset/utils';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
|
||||
type Props = BoxProps & {
|
||||
sourceName?: string;
|
||||
@@ -52,7 +53,7 @@ const RawSourceBox = ({ sourceId, sourceName = '', canView = true, ...props }: P
|
||||
: {})}
|
||||
{...props}
|
||||
>
|
||||
<Image src={icon} alt="" w={['14px', '16px']} mr={2} />
|
||||
<MyIcon name={icon as any} w={['14px', '16px']} mr={2} />
|
||||
<Box
|
||||
maxW={['200px', '300px']}
|
||||
className={props.className ?? 'textEllipsis'}
|
||||
|
@@ -38,7 +38,7 @@ const DatasetSelectContainer = ({
|
||||
parentId: path.parentId,
|
||||
parentName: path.parentName
|
||||
}))}
|
||||
FirstPathDom={t('core.chat.Select Mark Kb')}
|
||||
FirstPathDom={t('core.chat.Select dataset')}
|
||||
onClick={(e) => {
|
||||
setParentId(e);
|
||||
}}
|
||||
|
@@ -26,7 +26,8 @@ import type { AIChatModuleProps } from '@fastgpt/global/core/module/node/type.d'
|
||||
import type { AppSimpleEditConfigTemplateType } from '@fastgpt/global/core/app/type.d';
|
||||
import { SimpleModeTemplate_FastGPT_Universal } from '@/global/core/app/constants';
|
||||
import { getDocPath } from '@/web/common/system/doc';
|
||||
import PromptTextarea from '@/components/common/Textarea/PromptTextarea';
|
||||
import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor';
|
||||
import { PickerMenuItemType } from '@fastgpt/web/components/common/Textarea/PromptEditor/type';
|
||||
|
||||
const PromptTemplate = dynamic(() => import('@/components/PromptTemplate'));
|
||||
|
||||
@@ -35,13 +36,15 @@ const AIChatSettingsModal = ({
|
||||
onClose,
|
||||
onSuccess,
|
||||
defaultData,
|
||||
simpleModeTemplate = SimpleModeTemplate_FastGPT_Universal
|
||||
simpleModeTemplate = SimpleModeTemplate_FastGPT_Universal,
|
||||
pickerMenu = []
|
||||
}: {
|
||||
isAdEdit?: boolean;
|
||||
onClose: () => void;
|
||||
onSuccess: (e: AIChatModuleProps) => void;
|
||||
defaultData: AIChatModuleProps;
|
||||
simpleModeTemplate?: AppSimpleEditConfigTemplateType;
|
||||
pickerMenu?: PickerMenuItemType[];
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
@@ -60,7 +63,44 @@ const AIChatSettingsModal = ({
|
||||
chatModelList.find((item) => item.model === getValues(ModuleInputKeyEnum.aiModel))
|
||||
?.maxResponse || 4000
|
||||
);
|
||||
}, [getValues, refresh]);
|
||||
}, [getValues]);
|
||||
|
||||
const quoteTemplateVariables = (() => [
|
||||
...pickerMenu,
|
||||
{
|
||||
key: 'q',
|
||||
label: 'q',
|
||||
icon: 'core/app/simpleMode/variable'
|
||||
},
|
||||
{
|
||||
key: 'a',
|
||||
label: 'a',
|
||||
icon: 'core/app/simpleMode/variable'
|
||||
},
|
||||
{
|
||||
key: 'source',
|
||||
label: t('core.dataset.search.Source name'),
|
||||
icon: 'core/app/simpleMode/variable'
|
||||
},
|
||||
{
|
||||
key: 'sourceId',
|
||||
label: t('core.dataset.search.Source id'),
|
||||
icon: 'core/app/simpleMode/variable'
|
||||
},
|
||||
{
|
||||
key: 'index',
|
||||
label: t('core.dataset.search.Quote index'),
|
||||
icon: 'core/app/simpleMode/variable'
|
||||
}
|
||||
])();
|
||||
const quotePromptVariables = (() => [
|
||||
...pickerMenu,
|
||||
{
|
||||
key: 'quote',
|
||||
label: t('core.app.Quote templates'),
|
||||
icon: 'core/app/simpleMode/variable'
|
||||
}
|
||||
])();
|
||||
|
||||
const LabelStyles: BoxProps = {
|
||||
fontSize: ['sm', 'md']
|
||||
@@ -76,7 +116,7 @@ const AIChatSettingsModal = ({
|
||||
iconSrc="/imgs/module/AI.png"
|
||||
title={
|
||||
<>
|
||||
{t('app.AI Advanced Settings')}
|
||||
{t('common.More settings')}
|
||||
{feConfigs?.docUrl && (
|
||||
<Link
|
||||
href={getDocPath('/docs/use-cases/ai_settings/')}
|
||||
@@ -86,7 +126,7 @@ const AIChatSettingsModal = ({
|
||||
fontWeight={'normal'}
|
||||
fontSize={'md'}
|
||||
>
|
||||
查看说明
|
||||
{t('common.Read intro')}
|
||||
</Link>
|
||||
)}
|
||||
</>
|
||||
@@ -99,7 +139,7 @@ const AIChatSettingsModal = ({
|
||||
{isAdEdit && (
|
||||
<Flex alignItems={'center'}>
|
||||
<Box {...LabelStyles} w={'80px'}>
|
||||
返回AI内容
|
||||
{t('core.app.Ai response')}
|
||||
</Box>
|
||||
<Box flex={1} ml={'10px'}>
|
||||
<Switch
|
||||
@@ -117,13 +157,13 @@ const AIChatSettingsModal = ({
|
||||
{simpleModeTemplate?.systemForm?.aiSettings?.temperature && (
|
||||
<Flex alignItems={'center'} mb={10} mt={isAdEdit ? 8 : 5}>
|
||||
<Box {...LabelStyles} mr={2} w={'80px'}>
|
||||
温度
|
||||
{t('core.app.Temperature')}
|
||||
</Box>
|
||||
<Box flex={1} ml={'10px'}>
|
||||
<MySlider
|
||||
markList={[
|
||||
{ label: '严谨', value: 0 },
|
||||
{ label: '发散', value: 10 }
|
||||
{ label: t('core.app.deterministic'), value: 0 },
|
||||
{ label: t('core.app.Random'), value: 10 }
|
||||
]}
|
||||
width={'95%'}
|
||||
min={0}
|
||||
@@ -140,7 +180,7 @@ const AIChatSettingsModal = ({
|
||||
{simpleModeTemplate?.systemForm?.aiSettings?.maxToken && (
|
||||
<Flex alignItems={'center'} mt={12} mb={10}>
|
||||
<Box {...LabelStyles} mr={2} w={'80px'}>
|
||||
回复上限
|
||||
{t('core.app.Max tokens')}
|
||||
</Box>
|
||||
<Box flex={1} ml={'10px'}>
|
||||
<MySlider
|
||||
@@ -165,7 +205,7 @@ const AIChatSettingsModal = ({
|
||||
{simpleModeTemplate?.systemForm?.aiSettings?.quoteTemplate && (
|
||||
<Box>
|
||||
<Flex {...LabelStyles} mb={1}>
|
||||
引用内容模板
|
||||
{t('core.app.Quote templates')}
|
||||
<MyTooltip
|
||||
label={t('template.Quote Content Tip', {
|
||||
default: Prompt_QuoteTemplateList[0].value
|
||||
@@ -179,24 +219,24 @@ const AIChatSettingsModal = ({
|
||||
{...selectTemplateBtn}
|
||||
onClick={() =>
|
||||
setSelectTemplateData({
|
||||
title: '选择知识库提示词模板',
|
||||
title: t('core.app.Select quote template'),
|
||||
templates: Prompt_QuoteTemplateList
|
||||
})
|
||||
}
|
||||
>
|
||||
选择模板
|
||||
{t('common.Select template')}
|
||||
</Box>
|
||||
</Flex>
|
||||
|
||||
<PromptTextarea
|
||||
bg={'myWhite.400'}
|
||||
rows={8}
|
||||
<PromptEditor
|
||||
variables={quoteTemplateVariables}
|
||||
title={t('core.app.Quote templates')}
|
||||
placeholder={t('template.Quote Content Tip', {
|
||||
default: Prompt_QuoteTemplateList[0].value
|
||||
})}
|
||||
defaultValue={getValues(ModuleInputKeyEnum.aiChatQuoteTemplate)}
|
||||
onBlur={(e) => {
|
||||
setValue(ModuleInputKeyEnum.aiChatQuoteTemplate, e.target.value);
|
||||
onChange={(e) => {
|
||||
setValue(ModuleInputKeyEnum.aiChatQuoteTemplate, e);
|
||||
setRefresh(!refresh);
|
||||
}}
|
||||
/>
|
||||
@@ -205,7 +245,7 @@ const AIChatSettingsModal = ({
|
||||
{simpleModeTemplate?.systemForm?.aiSettings?.quotePrompt && (
|
||||
<Box mt={4}>
|
||||
<Flex {...LabelStyles} mb={1}>
|
||||
引用内容提示词
|
||||
{t('core.app.Quote prompt')}
|
||||
<MyTooltip
|
||||
label={t('template.Quote Prompt Tip', { default: Prompt_QuotePromptList[0].value })}
|
||||
forceShow
|
||||
@@ -213,16 +253,16 @@ const AIChatSettingsModal = ({
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
<PromptTextarea
|
||||
bg={'myWhite.400'}
|
||||
rows={11}
|
||||
<PromptEditor
|
||||
variables={quotePromptVariables}
|
||||
title={t('core.app.Quote prompt')}
|
||||
h={220}
|
||||
placeholder={t('template.Quote Prompt Tip', {
|
||||
default: Prompt_QuotePromptList[0].value
|
||||
})}
|
||||
defaultValue={getValues(ModuleInputKeyEnum.aiChatQuotePrompt)}
|
||||
onBlur={(e) => {
|
||||
setValue(ModuleInputKeyEnum.aiChatQuotePrompt, e.target.value);
|
||||
setRefresh(!refresh);
|
||||
onChange={(e) => {
|
||||
setValue(ModuleInputKeyEnum.aiChatQuotePrompt, e);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
@@ -230,10 +270,10 @@ const AIChatSettingsModal = ({
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button variant={'whiteBase'} onClick={onClose}>
|
||||
{t('Cancel')}
|
||||
{t('common.Close')}
|
||||
</Button>
|
||||
<Button ml={4} onClick={handleSubmit(onSuccess)}>
|
||||
{t('Confirm')}
|
||||
{t('common.Confirm')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
{!!selectTemplateData && (
|
||||
|
@@ -15,12 +15,12 @@ import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import MySlider from '@/components/Slider';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { reRankModelList } from '@/web/common/system/staticData';
|
||||
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { DatasetSearchModeMap } from '@fastgpt/global/core/dataset/constant';
|
||||
import { DatasetSearchModeMap } from '@fastgpt/global/core/dataset/constants';
|
||||
import MyRadio from '@/components/common/MyRadio';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
|
||||
@@ -136,7 +136,7 @@ const DatasetParamsModal = ({
|
||||
|
||||
{limit !== undefined && (
|
||||
<Box display={['block', 'flex']} py={8} mt={3}>
|
||||
<Box flex={'0 0 100px'} mb={[8, 0]}>
|
||||
<Box flex={'0 0 120px'} mb={[8, 0]}>
|
||||
{t('core.dataset.search.Max Tokens')}
|
||||
<MyTooltip label={t('core.dataset.search.Max Tokens Tips')} forceShow>
|
||||
<QuestionOutlineIcon ml={1} />
|
||||
@@ -162,7 +162,7 @@ const DatasetParamsModal = ({
|
||||
)}
|
||||
{showSimilarity && (
|
||||
<Box display={['block', 'flex']} py={8}>
|
||||
<Box flex={'0 0 100px'} mb={[8, 0]}>
|
||||
<Box flex={'0 0 120px'} mb={[8, 0]}>
|
||||
{t('core.dataset.search.Min Similarity')}
|
||||
<MyTooltip label={t('core.dataset.search.Min Similarity Tips')} forceShow>
|
||||
<QuestionOutlineIcon ml={1} />
|
||||
@@ -189,7 +189,7 @@ const DatasetParamsModal = ({
|
||||
|
||||
{searchEmptyText !== undefined && (
|
||||
<Box display={['block', 'flex']} pt={3}>
|
||||
<Box flex={'0 0 100px'} mb={[2, 0]}>
|
||||
<Box flex={'0 0 120px'} mb={[2, 0]}>
|
||||
{t('core.dataset.search.Empty result response')}
|
||||
</Box>
|
||||
<Box flex={1}>
|
||||
|
@@ -15,7 +15,7 @@ import type { SelectedDatasetType } from '@fastgpt/global/core/module/api.d';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||
import DatasetSelectContainer, { useDatasetSelect } from '@/components/core/dataset/SelectModal';
|
||||
|
@@ -6,7 +6,6 @@ import type { SelectAppItemType } from '@fastgpt/global/core/module/type';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useLoading } from '@/web/common/hooks/useLoading';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { useAppStore } from '@/web/core/app/store/useAppStore';
|
||||
|
||||
const SelectAppModal = ({
|
||||
@@ -84,7 +83,7 @@ const SelectAppModal = ({
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button variant={'whiteBase'} onClick={onClose}>
|
||||
{t('Cancel')}
|
||||
{t('common.Close')}
|
||||
</Button>
|
||||
<Button
|
||||
ml={2}
|
||||
@@ -101,7 +100,7 @@ const SelectAppModal = ({
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
{t('Confirm')}
|
||||
{t('common.Confirm')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
<Loading loading={isLoading} fixed={false} />
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { BezierEdge, getBezierPath, EdgeLabelRenderer, EdgeProps } from 'reactflow';
|
||||
import { onDelConnect } from '../../FlowProvider';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
@@ -17,7 +17,7 @@ const ButtonEdge = (props: EdgeProps) => {
|
||||
style = {}
|
||||
} = props;
|
||||
|
||||
const [edgePath, labelX, labelY] = getBezierPath({
|
||||
const [labelX, labelY] = getBezierPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourcePosition,
|
||||
@@ -26,19 +26,8 @@ const ButtonEdge = (props: EdgeProps) => {
|
||||
targetPosition
|
||||
});
|
||||
|
||||
const edgeStyle: React.CSSProperties = {
|
||||
...style,
|
||||
...(selected
|
||||
? {
|
||||
strokeWidth: 4,
|
||||
stroke: '#3370ff'
|
||||
}
|
||||
: { strokeWidth: 2, stroke: '#BDC1C5' })
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<BezierEdge {...props} style={edgeStyle} />
|
||||
const memoEdgeLabel = useMemo(() => {
|
||||
return (
|
||||
<EdgeLabelRenderer>
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
@@ -66,6 +55,27 @@ const ButtonEdge = (props: EdgeProps) => {
|
||||
></MyIcon>
|
||||
</Flex>
|
||||
</EdgeLabelRenderer>
|
||||
);
|
||||
}, [id, labelX, labelY, selected]);
|
||||
|
||||
const memoBezierEdge = useMemo(() => {
|
||||
const edgeStyle: React.CSSProperties = {
|
||||
...style,
|
||||
...(selected
|
||||
? {
|
||||
strokeWidth: 4,
|
||||
stroke: '#3370ff'
|
||||
}
|
||||
: { strokeWidth: 2, stroke: '#BDC1C5' })
|
||||
};
|
||||
|
||||
return <BezierEdge {...props} style={edgeStyle} />;
|
||||
}, [props, selected, style]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{memoBezierEdge}
|
||||
{memoEdgeLabel}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@@ -9,7 +9,7 @@ const QGSwitch = (props: SwitchProps) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'core/app/questionGuide'} mr={2} w={'16px'} />
|
||||
<MyIcon name={'core/app/questionGuide'} mr={2} w={'20px'} />
|
||||
<Box>{t('core.app.Next Step Guide')}</Box>
|
||||
<MyTooltip label={t('core.app.Question Guide Tip')} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
|
@@ -71,7 +71,7 @@ const TTSSelect = ({
|
||||
|
||||
return (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'core/app/tts'} mr={2} w={'16px'} />
|
||||
<MyIcon name={'core/app/simpleMode/tts'} mr={2} w={'20px'} />
|
||||
<Box>{t('core.app.TTS')}</Box>
|
||||
<MyTooltip label={t('core.app.TTS Tip')} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
@@ -93,7 +93,7 @@ const TTSSelect = ({
|
||||
<MyModal
|
||||
title={
|
||||
<>
|
||||
<MyIcon name={'core/app/tts'} mr={2} w={'20px'} />
|
||||
<MyIcon name={'core/app/simpleMode/tts'} mr={2} w={'20px'} />
|
||||
{t('core.app.TTS')}
|
||||
</>
|
||||
}
|
||||
|
@@ -38,6 +38,7 @@ import { variableTip } from '@fastgpt/global/core/module/template/tip';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import MyRadio from '@/components/common/MyRadio';
|
||||
import { formatVariablesIcon } from '@fastgpt/global/core/module/utils';
|
||||
|
||||
const VariableEdit = ({
|
||||
variables,
|
||||
@@ -101,16 +102,13 @@ const VariableEdit = ({
|
||||
};
|
||||
|
||||
const formatVariables = useMemo(() => {
|
||||
return variables.map((item) => ({
|
||||
...item,
|
||||
icon: VariableTypeList.find((type) => type.value === item.type)?.icon
|
||||
}));
|
||||
}, [VariableTypeList, variables]);
|
||||
return formatVariablesIcon(variables);
|
||||
}, [variables]);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Flex alignItems={'center'}>
|
||||
<Image alt={''} src={'/imgs/module/variable.png'} objectFit={'contain'} w={'18px'} />
|
||||
<MyIcon name={'core/app/simpleMode/variable'} w={'20px'} />
|
||||
<Box ml={2} flex={1}>
|
||||
{t('core.module.Variable')}
|
||||
<MyTooltip label={variableTip} forceShow>
|
||||
@@ -179,7 +177,7 @@ const VariableEdit = ({
|
||||
</Box>
|
||||
)}
|
||||
<MyModal
|
||||
iconSrc="/imgs/module/variable.png"
|
||||
iconSrc="core/app/simpleMode/variable"
|
||||
title={t('core.module.Variable Setting')}
|
||||
isOpen={isOpenEdit}
|
||||
onClose={onCloseEdit}
|
||||
@@ -342,6 +340,6 @@ export const defaultVariable: VariableItemType = {
|
||||
enums: [{ value: '' }]
|
||||
};
|
||||
export const addVariable = () => {
|
||||
const newVariable = { ...defaultVariable, key: nanoid(), id: '' };
|
||||
const newVariable = { ...defaultVariable, key: '', id: '' };
|
||||
return newVariable;
|
||||
};
|
||||
|
@@ -126,7 +126,7 @@ const NodeCQNode = React.memo(function NodeCQNode({ data }: { data: FlowModuleIt
|
||||
});
|
||||
}}
|
||||
>
|
||||
添加问题类型
|
||||
{t('core.module.Add question type')}
|
||||
</Button>
|
||||
</Box>
|
||||
);
|
||||
|
@@ -1,23 +1,10 @@
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useMemo, useTransition } from 'react';
|
||||
import { NodeProps } from 'reactflow';
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
Textarea,
|
||||
useTheme,
|
||||
Table,
|
||||
Thead,
|
||||
Tbody,
|
||||
Tr,
|
||||
Th,
|
||||
Td,
|
||||
TableContainer,
|
||||
Switch
|
||||
} from '@chakra-ui/react';
|
||||
import { Box, Flex, Textarea, useTheme } from '@chakra-ui/react';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { FlowModuleItemType, ModuleItemType } from '@fastgpt/global/core/module/type.d';
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { welcomeTextTip, variableTip } from '@fastgpt/global/core/module/template/tip';
|
||||
import { welcomeTextTip } from '@fastgpt/global/core/module/template/tip';
|
||||
import { onChangeNode } from '../../FlowProvider';
|
||||
|
||||
import VariableEdit from '../modules/VariableEdit';
|
||||
@@ -29,6 +16,7 @@ import type { VariableItemType } from '@fastgpt/global/core/module/type.d';
|
||||
import QGSwitch from '@/components/core/module/Flow/components/modules/QGSwitch';
|
||||
import TTSSelect from '@/components/core/module/Flow/components/modules/TTSSelect';
|
||||
import { splitGuideModule } from '@fastgpt/global/core/module/utils';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
const NodeUserGuide = React.memo(function NodeUserGuide({ data }: { data: FlowModuleItemType }) {
|
||||
const theme = useTheme();
|
||||
@@ -56,19 +44,18 @@ export default function Node({ data }: NodeProps<FlowModuleItemType>) {
|
||||
return <NodeUserGuide data={data} />;
|
||||
}
|
||||
export function WelcomeText({ data }: { data: FlowModuleItemType }) {
|
||||
const { t } = useTranslation();
|
||||
const { inputs, moduleId } = data;
|
||||
const [, startTst] = useTransition();
|
||||
|
||||
const welcomeText = useMemo(
|
||||
() => inputs.find((item) => item.key === ModuleInputKeyEnum.welcomeText),
|
||||
[inputs]
|
||||
);
|
||||
const welcomeText = inputs.find((item) => item.key === ModuleInputKeyEnum.welcomeText);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex mb={1} alignItems={'center'}>
|
||||
<MyIcon name={'core/modules/welcomeText'} mr={2} w={'16px'} color={'#E74694'} />
|
||||
<Box>开场白</Box>
|
||||
<MyTooltip label={welcomeTextTip} forceShow>
|
||||
<Box>{t('core.app.Welcome Text')}</Box>
|
||||
<MyTooltip label={t(welcomeTextTip)} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
@@ -79,16 +66,18 @@ export function WelcomeText({ data }: { data: FlowModuleItemType }) {
|
||||
resize={'both'}
|
||||
defaultValue={welcomeText.value}
|
||||
bg={'myWhite.500'}
|
||||
placeholder={welcomeTextTip}
|
||||
placeholder={t(welcomeTextTip)}
|
||||
onChange={(e) => {
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
key: ModuleInputKeyEnum.welcomeText,
|
||||
type: 'updateInput',
|
||||
value: {
|
||||
...welcomeText,
|
||||
value: e.target.value
|
||||
}
|
||||
startTst(() => {
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
key: ModuleInputKeyEnum.welcomeText,
|
||||
type: 'updateInput',
|
||||
value: {
|
||||
...welcomeText,
|
||||
value: e.target.value
|
||||
}
|
||||
});
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
@@ -1,60 +0,0 @@
|
||||
/* Abandon */
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { NodeProps } from 'reactflow';
|
||||
import { Box, Button, Table, Thead, Tbody, Tr, Th, Td, TableContainer } from '@chakra-ui/react';
|
||||
import { AddIcon } from '@chakra-ui/icons';
|
||||
import NodeCard from '../../render/NodeCard';
|
||||
import { FlowModuleItemType } from '@fastgpt/global/core/module/type.d';
|
||||
import Container from '../../modules/Container';
|
||||
import { VariableInputEnum, ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import type { VariableItemType } from '@fastgpt/global/core/module/type.d';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);
|
||||
import VariableEditModal, { addVariable } from '../../modules/VariableEdit';
|
||||
import { onChangeNode } from '../../../FlowProvider';
|
||||
|
||||
export const defaultVariable: VariableItemType = {
|
||||
id: nanoid(),
|
||||
key: 'key',
|
||||
label: 'label',
|
||||
type: VariableInputEnum.input,
|
||||
required: true,
|
||||
maxLen: 50,
|
||||
enums: [{ value: '' }]
|
||||
};
|
||||
|
||||
const NodeUserGuide = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||
const { inputs, moduleId } = data;
|
||||
|
||||
const variables = useMemo(
|
||||
() =>
|
||||
(inputs.find((item) => item.key === ModuleInputKeyEnum.variables)
|
||||
?.value as VariableItemType[]) || [],
|
||||
[inputs]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<NodeCard minW={'300px'} {...data}>
|
||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
||||
<VariableEditModal
|
||||
variables={variables}
|
||||
onChange={(e) =>
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
key: ModuleInputKeyEnum.variables,
|
||||
type: 'updateInput',
|
||||
value: {
|
||||
...inputs.find((item) => item.key === ModuleInputKeyEnum.variables),
|
||||
value: e
|
||||
}
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Container>
|
||||
</NodeCard>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default React.memo(NodeUserGuide);
|
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import type { FlowNodeInputItemType } from '@fastgpt/global/core/module/node/type';
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
@@ -6,7 +6,7 @@ import dynamic from 'next/dynamic';
|
||||
|
||||
import InputLabel from './Label';
|
||||
import type { RenderInputProps } from './type.d';
|
||||
import { getFlowStore, type useFlowProviderStoreType } from '../../../FlowProvider';
|
||||
import { useFlowProviderStore } from '../../../FlowProvider';
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
|
||||
const RenderList: {
|
||||
@@ -77,8 +77,8 @@ type Props = {
|
||||
moduleId: string;
|
||||
CustomComponent?: Record<string, (e: FlowNodeInputItemType) => React.ReactNode>;
|
||||
};
|
||||
const RenderInput = ({ flowInputList, moduleId, CustomComponent = {} }: Props) => {
|
||||
const [mode, setMode] = useState<useFlowProviderStoreType['mode']>('app');
|
||||
const RenderInput = ({ flowInputList, moduleId, CustomComponent }: Props) => {
|
||||
const { mode } = useFlowProviderStore();
|
||||
|
||||
const sortInputs = useMemo(
|
||||
() =>
|
||||
@@ -109,48 +109,43 @@ const RenderInput = ({ flowInputList, moduleId, CustomComponent = {} }: Props) =
|
||||
[mode, sortInputs]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
async () => {
|
||||
const { mode } = await getFlowStore();
|
||||
setMode(mode);
|
||||
};
|
||||
}, []);
|
||||
const memoCustomComponent = useMemo(() => CustomComponent || {}, [CustomComponent]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{filterInputs.map((input) => {
|
||||
const RenderComponent = (() => {
|
||||
if (input.type === FlowNodeInputTypeEnum.custom && CustomComponent[input.key]) {
|
||||
return <>{CustomComponent[input.key]({ ...input })}</>;
|
||||
}
|
||||
const Component = RenderList.find((item) => item.types.includes(input.type))?.Component;
|
||||
const Render = useMemo(() => {
|
||||
return filterInputs.map((input) => {
|
||||
const RenderComponent = (() => {
|
||||
if (input.type === FlowNodeInputTypeEnum.custom && memoCustomComponent[input.key]) {
|
||||
return <>{memoCustomComponent[input.key]({ ...input })}</>;
|
||||
}
|
||||
const Component = RenderList.find((item) => item.types.includes(input.type))?.Component;
|
||||
|
||||
if (!Component) return null;
|
||||
return <Component inputs={filterInputs} item={input} moduleId={moduleId} />;
|
||||
})();
|
||||
if (!Component) return null;
|
||||
return <Component inputs={filterInputs} item={input} moduleId={moduleId} />;
|
||||
})();
|
||||
|
||||
return (
|
||||
<Box key={input.key} _notLast={{ mb: 7 }} position={'relative'}>
|
||||
{input.key === ModuleInputKeyEnum.userChatInput && (
|
||||
<UserChatInput inputs={filterInputs} item={input} moduleId={moduleId} />
|
||||
)}
|
||||
{input.type !== FlowNodeInputTypeEnum.hidden && (
|
||||
<>
|
||||
{!!input.label && (
|
||||
<InputLabel moduleId={moduleId} inputKey={input.key} mode={mode} {...input} />
|
||||
)}
|
||||
{!!RenderComponent && (
|
||||
<Box mt={2} className={'nodrag'}>
|
||||
{RenderComponent}
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<Box key={input.key} _notLast={{ mb: 7 }} position={'relative'}>
|
||||
{input.key === ModuleInputKeyEnum.userChatInput && (
|
||||
<UserChatInput inputs={filterInputs} item={input} moduleId={moduleId} />
|
||||
)}
|
||||
{input.type !== FlowNodeInputTypeEnum.hidden && (
|
||||
<>
|
||||
{!!input.label && (
|
||||
<InputLabel moduleId={moduleId} inputKey={input.key} mode={mode} {...input} />
|
||||
)}
|
||||
{!!RenderComponent && (
|
||||
<Box mt={2} className={'nodrag'}>
|
||||
{RenderComponent}
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
});
|
||||
}, [memoCustomComponent, filterInputs, mode, moduleId]);
|
||||
|
||||
return <>{Render}</>;
|
||||
};
|
||||
|
||||
export default React.memo(RenderInput);
|
||||
|
@@ -1,20 +1,39 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import type { RenderInputProps } from '../type';
|
||||
import { onChangeNode } from '../../../../FlowProvider';
|
||||
import { getFlowStore, onChangeNode, useFlowProviderStoreType } from '../../../../FlowProvider';
|
||||
import { Box, Button, Flex, Grid, useDisclosure, useTheme } from '@chakra-ui/react';
|
||||
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||
import { SelectedDatasetType } from '@fastgpt/global/core/module/api';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import DatasetSelectModal from '@/components/core/module/DatasetSelectModal';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { chatModelList } from '@/web/common/system/staticData';
|
||||
|
||||
const SelectDatasetRender = ({ item, moduleId }: RenderInputProps) => {
|
||||
import dynamic from 'next/dynamic';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
|
||||
const DatasetSelectModal = dynamic(() => import('@/components/core/module/DatasetSelectModal'));
|
||||
const DatasetParamsModal = dynamic(() => import('@/components/core/module/DatasetParamsModal'));
|
||||
|
||||
const SelectDatasetRender = ({ inputs = [], item, moduleId }: RenderInputProps) => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const [nodes, setNodes] = useState<useFlowProviderStoreType['nodes']>([]);
|
||||
const [data, setData] = useState({
|
||||
searchMode: DatasetSearchModeEnum.embedding,
|
||||
limit: 5,
|
||||
similarity: 0.5,
|
||||
usingReRank: false
|
||||
});
|
||||
|
||||
const { allDatasets, loadAllDatasets } = useDatasetStore();
|
||||
const {
|
||||
isOpen: isOpenKbSelect,
|
||||
onOpen: onOpenKbSelect,
|
||||
onClose: onCloseKbSelect
|
||||
isOpen: isOpenDatasetSelect,
|
||||
onOpen: onOpenDatasetSelect,
|
||||
onClose: onCloseDatasetSelect
|
||||
} = useDisclosure();
|
||||
|
||||
const selectedDatasets = useMemo(() => {
|
||||
@@ -22,14 +41,68 @@ const SelectDatasetRender = ({ item, moduleId }: RenderInputProps) => {
|
||||
return allDatasets.filter((dataset) => value?.find((item) => item.datasetId === dataset._id));
|
||||
}, [allDatasets, item.value]);
|
||||
|
||||
const tokenLimit = useMemo(() => {
|
||||
let maxTokens = 3000;
|
||||
|
||||
nodes.forEach((item) => {
|
||||
if (item.type === FlowNodeTypeEnum.chatNode) {
|
||||
const model =
|
||||
item.data.inputs.find((item) => item.key === ModuleInputKeyEnum.aiModel)?.value || '';
|
||||
const quoteMaxToken =
|
||||
chatModelList.find((item) => item.model === model)?.quoteMaxToken || 3000;
|
||||
|
||||
maxTokens = Math.max(maxTokens, quoteMaxToken);
|
||||
}
|
||||
});
|
||||
|
||||
return maxTokens;
|
||||
}, [nodes]);
|
||||
|
||||
const {
|
||||
isOpen: isOpenDatasetPrams,
|
||||
onOpen: onOpenDatasetParams,
|
||||
onClose: onCloseDatasetParams
|
||||
} = useDisclosure();
|
||||
|
||||
useQuery(['loadAllDatasets'], loadAllDatasets);
|
||||
|
||||
useEffect(() => {
|
||||
inputs.forEach((input) => {
|
||||
// @ts-ignore
|
||||
if (data[input.key] !== undefined) {
|
||||
setData((state) => ({
|
||||
...state,
|
||||
[input.key]: input.value
|
||||
}));
|
||||
}
|
||||
});
|
||||
}, [inputs]);
|
||||
|
||||
useEffect(() => {
|
||||
async () => {
|
||||
const { nodes } = await getFlowStore();
|
||||
setNodes(nodes);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid gridTemplateColumns={'repeat(2, minmax(0, 1fr))'} gridGap={4} minW={'350px'} w={'100%'}>
|
||||
<Button h={'36px'} onClick={onOpenKbSelect}>
|
||||
选择知识库
|
||||
<Button
|
||||
h={'36px'}
|
||||
leftIcon={<MyIcon name={'common/selectLight'} w={'14px'} />}
|
||||
onClick={onOpenDatasetSelect}
|
||||
>
|
||||
{t('common.Choose')}
|
||||
</Button>
|
||||
{/* <Button
|
||||
h={'36px'}
|
||||
variant={'whitePrimary'}
|
||||
leftIcon={<MyIcon name={'common/settingLight'} w={'14px'} />}
|
||||
onClick={onOpenDatasetParams}
|
||||
>
|
||||
{t('core.dataset.search.Params Setting')}
|
||||
</Button> */}
|
||||
{selectedDatasets.map((item) => (
|
||||
<Flex
|
||||
key={item._id}
|
||||
@@ -53,9 +126,9 @@ const SelectDatasetRender = ({ item, moduleId }: RenderInputProps) => {
|
||||
</Flex>
|
||||
))}
|
||||
</Grid>
|
||||
{isOpenKbSelect && (
|
||||
{isOpenDatasetSelect && (
|
||||
<DatasetSelectModal
|
||||
isOpen={isOpenKbSelect}
|
||||
isOpen={isOpenDatasetSelect}
|
||||
defaultSelectedDatasets={item.value}
|
||||
onChange={(e) => {
|
||||
onChangeNode({
|
||||
@@ -68,9 +141,32 @@ const SelectDatasetRender = ({ item, moduleId }: RenderInputProps) => {
|
||||
}
|
||||
});
|
||||
}}
|
||||
onClose={onCloseKbSelect}
|
||||
onClose={onCloseDatasetSelect}
|
||||
/>
|
||||
)}
|
||||
{/* {isOpenDatasetPrams && (
|
||||
<DatasetParamsModal
|
||||
{...data}
|
||||
maxTokens={tokenLimit}
|
||||
onClose={onCloseDatasetParams}
|
||||
onSuccess={(e) => {
|
||||
for (let key in e) {
|
||||
const item = inputs.find((input) => input.key === key);
|
||||
if (!item) continue;
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
type: 'updateInput',
|
||||
key,
|
||||
value: {
|
||||
...item,
|
||||
//@ts-ignore
|
||||
value: e[key]
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)} */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import type { RenderInputProps } from '../type';
|
||||
import { getFlowStore, onChangeNode, useFlowProviderStoreType } from '../../../../FlowProvider';
|
||||
import { onChangeNode, useFlowProviderStore } from '../../../../FlowProvider';
|
||||
import { Button, useDisclosure } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { chatModelList } from '@/web/common/system/staticData';
|
||||
@@ -11,7 +11,7 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import DatasetParamsModal from '@/components/core/module/DatasetParamsModal';
|
||||
|
||||
const SelectDatasetParam = ({ inputs = [], moduleId }: RenderInputProps) => {
|
||||
const [nodes, setNodes] = useState<useFlowProviderStoreType['nodes']>([]);
|
||||
const { nodes } = useFlowProviderStore();
|
||||
|
||||
const { t } = useTranslation();
|
||||
const [data, setData] = useState({
|
||||
@@ -52,47 +52,44 @@ const SelectDatasetParam = ({ inputs = [], moduleId }: RenderInputProps) => {
|
||||
});
|
||||
}, [inputs]);
|
||||
|
||||
useEffect(() => {
|
||||
async () => {
|
||||
const { nodes } = await getFlowStore();
|
||||
setNodes(nodes);
|
||||
};
|
||||
}, []);
|
||||
const Render = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
variant={'whitePrimary'}
|
||||
leftIcon={<MyIcon name={'common/settingLight'} w={'14px'} />}
|
||||
onClick={onOpen}
|
||||
>
|
||||
{t('core.dataset.search.Params Setting')}
|
||||
</Button>
|
||||
{isOpen && (
|
||||
<DatasetParamsModal
|
||||
{...data}
|
||||
maxTokens={tokenLimit}
|
||||
onClose={onClose}
|
||||
onSuccess={(e) => {
|
||||
for (let key in e) {
|
||||
const item = inputs.find((input) => input.key === key);
|
||||
if (!item) continue;
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
type: 'updateInput',
|
||||
key,
|
||||
value: {
|
||||
...item,
|
||||
//@ts-ignore
|
||||
value: e[key]
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}, [data, inputs, isOpen, moduleId, onClose, onOpen, t, tokenLimit]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
variant={'whitePrimary'}
|
||||
leftIcon={<MyIcon name={'common/settingLight'} w={'14px'} />}
|
||||
onClick={onOpen}
|
||||
>
|
||||
{t('core.dataset.search.Params Setting')}
|
||||
</Button>
|
||||
{isOpen && (
|
||||
<DatasetParamsModal
|
||||
{...data}
|
||||
maxTokens={tokenLimit}
|
||||
onClose={onClose}
|
||||
onSuccess={(e) => {
|
||||
for (let key in e) {
|
||||
const item = inputs.find((input) => input.key === key);
|
||||
if (!item) continue;
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
type: 'updateInput',
|
||||
key,
|
||||
value: {
|
||||
...item,
|
||||
//@ts-ignore
|
||||
value: e[key]
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
return Render;
|
||||
};
|
||||
|
||||
export default React.memo(SelectDatasetParam);
|
||||
|
@@ -1,38 +1,53 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useMemo, useTransition } from 'react';
|
||||
import type { RenderInputProps } from '../type';
|
||||
import { onChangeNode } from '../../../../FlowProvider';
|
||||
import { useFlowProviderStore, onChangeNode } from '../../../../FlowProvider';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import PromptTextarea from '@/components/common/Textarea/PromptTextarea';
|
||||
import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor';
|
||||
import {
|
||||
formatVariablesIcon,
|
||||
getGuideModule,
|
||||
splitGuideModule
|
||||
} from '@fastgpt/global/core/module/utils';
|
||||
|
||||
const TextareaRender = ({ item, moduleId }: RenderInputProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [, startTst] = useTransition();
|
||||
const { nodes } = useFlowProviderStore();
|
||||
|
||||
const update = useCallback(
|
||||
(value: string) => {
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
type: 'updateInput',
|
||||
key: item.key,
|
||||
value: {
|
||||
...item,
|
||||
value
|
||||
}
|
||||
// get variable
|
||||
const variables = useMemo(
|
||||
() =>
|
||||
formatVariablesIcon(
|
||||
splitGuideModule(getGuideModule(nodes.map((node) => node.data)))?.variableModules || []
|
||||
),
|
||||
[nodes]
|
||||
);
|
||||
|
||||
const onChange = useCallback(
|
||||
(e: string) => {
|
||||
startTst(() => {
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
type: 'updateInput',
|
||||
key: item.key,
|
||||
value: {
|
||||
...item,
|
||||
value: e
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
[item, moduleId]
|
||||
);
|
||||
|
||||
return (
|
||||
<PromptTextarea
|
||||
<PromptEditor
|
||||
variables={variables}
|
||||
title={t(item.label)}
|
||||
rows={5}
|
||||
bg={'myWhite.400'}
|
||||
h={150}
|
||||
placeholder={t(item.placeholder || '')}
|
||||
resize={'both'}
|
||||
defaultValue={item.value}
|
||||
onBlur={(e) => {
|
||||
update(e.target.value);
|
||||
}}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import ReactFlow, { Background, Controls, ReactFlowProvider } from 'reactflow';
|
||||
import { Box, Flex, IconButton, useDisclosure } from '@chakra-ui/react';
|
||||
import { SmallCloseIcon } from '@chakra-ui/icons';
|
||||
@@ -15,7 +15,6 @@ import 'reactflow/dist/style.css';
|
||||
const NodeSimple = dynamic(() => import('./components/nodes/NodeSimple'));
|
||||
const nodeTypes: Record<`${FlowNodeTypeEnum}`, any> = {
|
||||
[FlowNodeTypeEnum.userGuide]: dynamic(() => import('./components/nodes/NodeUserGuide')),
|
||||
[FlowNodeTypeEnum.variable]: dynamic(() => import('./components/nodes/abandon/NodeVariable')),
|
||||
[FlowNodeTypeEnum.questionInput]: dynamic(() => import('./components/nodes/NodeQuestionInput')),
|
||||
[FlowNodeTypeEnum.historyNode]: NodeSimple,
|
||||
[FlowNodeTypeEnum.chatNode]: NodeSimple,
|
||||
@@ -38,6 +37,16 @@ const Container = React.memo(function Container() {
|
||||
const { reactFlowWrapper, nodes, onNodesChange, edges, onEdgesChange, onConnect } =
|
||||
useFlowProviderStore();
|
||||
|
||||
const memoRenderTools = useMemo(
|
||||
() => (
|
||||
<>
|
||||
<Background />
|
||||
<Controls position={'bottom-right'} style={{ display: 'flex' }} showInteractive={false} />
|
||||
</>
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
ref={reactFlowWrapper}
|
||||
@@ -64,8 +73,7 @@ const Container = React.memo(function Container() {
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Background />
|
||||
<Controls position={'bottom-right'} style={{ display: 'flex' }} showInteractive={false} />
|
||||
{memoRenderTools}
|
||||
</ReactFlow>
|
||||
);
|
||||
});
|
||||
@@ -81,48 +89,54 @@ const Flow = ({
|
||||
onClose: onCloseTemplate
|
||||
} = useDisclosure();
|
||||
|
||||
const memoRenderContainer = useMemo(() => {
|
||||
return (
|
||||
<Box
|
||||
minH={'400px'}
|
||||
flex={'1 0 0'}
|
||||
w={'100%'}
|
||||
h={0}
|
||||
position={'relative'}
|
||||
onContextMenu={(e) => {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}}
|
||||
>
|
||||
{/* open module template */}
|
||||
<IconButton
|
||||
position={'absolute'}
|
||||
top={5}
|
||||
left={5}
|
||||
size={'mdSquare'}
|
||||
borderRadius={'50%'}
|
||||
icon={<SmallCloseIcon fontSize={'26px'} />}
|
||||
transform={isOpenTemplate ? '' : 'rotate(135deg)'}
|
||||
transition={'0.2s ease'}
|
||||
aria-label={''}
|
||||
zIndex={1}
|
||||
boxShadow={'2px 2px 6px #85b1ff'}
|
||||
onClick={() => {
|
||||
isOpenTemplate ? onCloseTemplate() : onOpenTemplate();
|
||||
}}
|
||||
/>
|
||||
|
||||
<Container {...data} />
|
||||
|
||||
<ModuleTemplateList
|
||||
templates={templates}
|
||||
isOpen={isOpenTemplate}
|
||||
onClose={onCloseTemplate}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}, [data, isOpenTemplate, onCloseTemplate, onOpenTemplate, templates]);
|
||||
|
||||
return (
|
||||
<Box h={'100%'} position={'fixed'} zIndex={999} top={0} left={0} right={0} bottom={0}>
|
||||
<ReactFlowProvider>
|
||||
<Flex h={'100%'} flexDirection={'column'} bg={'#fff'}>
|
||||
{Header}
|
||||
<Box
|
||||
minH={'400px'}
|
||||
flex={'1 0 0'}
|
||||
w={'100%'}
|
||||
h={0}
|
||||
position={'relative'}
|
||||
onContextMenu={(e) => {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}}
|
||||
>
|
||||
{/* open module template */}
|
||||
<IconButton
|
||||
position={'absolute'}
|
||||
top={5}
|
||||
left={5}
|
||||
size={'mdSquare'}
|
||||
borderRadius={'50%'}
|
||||
icon={<SmallCloseIcon fontSize={'26px'} />}
|
||||
transform={isOpenTemplate ? '' : 'rotate(135deg)'}
|
||||
transition={'0.2s ease'}
|
||||
aria-label={''}
|
||||
zIndex={1}
|
||||
boxShadow={'2px 2px 6px #85b1ff'}
|
||||
onClick={() => {
|
||||
isOpenTemplate ? onCloseTemplate() : onOpenTemplate();
|
||||
}}
|
||||
/>
|
||||
|
||||
<Container {...data} />
|
||||
|
||||
<ModuleTemplateList
|
||||
templates={templates}
|
||||
isOpen={isOpenTemplate}
|
||||
onClose={onCloseTemplate}
|
||||
/>
|
||||
</Box>
|
||||
{memoRenderContainer}
|
||||
</Flex>
|
||||
</ReactFlowProvider>
|
||||
</Box>
|
||||
|
@@ -81,7 +81,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
<Box flex={1}>
|
||||
<Flex alignItems={'flex-end'}>
|
||||
<Box fontSize={['md', 'xl']} fontWeight={'bold'}>
|
||||
API 秘钥管理
|
||||
{t('support.openapi.Api manager')}
|
||||
</Box>
|
||||
{feConfigs?.docUrl && (
|
||||
<Link
|
||||
@@ -90,7 +90,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
ml={1}
|
||||
color={'primary.500'}
|
||||
>
|
||||
查看文档
|
||||
{t('common.Read document')}
|
||||
</Link>
|
||||
)}
|
||||
</Flex>
|
||||
@@ -106,10 +106,10 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
userSelect={'none'}
|
||||
onClick={() => copyData(baseUrl, '已复制 API 地址')}
|
||||
onClick={() => copyData(baseUrl, t('support.openapi.Copy success'))}
|
||||
>
|
||||
<Box border={theme.borders.md} px={2} borderRadius={'md'} fontSize={'sm'}>
|
||||
API根地址
|
||||
{t('support.openapi.Api baseurl')}
|
||||
</Box>
|
||||
<Box ml={2} color={'myGray.900'} fontSize={['sm', 'md']}>
|
||||
{baseUrl}
|
||||
@@ -127,7 +127,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
})
|
||||
}
|
||||
>
|
||||
新建
|
||||
{t('common.New Create')}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
@@ -137,16 +137,16 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
<Tr>
|
||||
<Th>{t('Name')}</Th>
|
||||
<Th>Api Key</Th>
|
||||
<Th>已用额度(¥)</Th>
|
||||
<Th>{t('support.openapi.Usage')}</Th>
|
||||
{feConfigs?.isPlus && (
|
||||
<>
|
||||
<Th>最大额度(¥)</Th>
|
||||
<Th>过期时间</Th>
|
||||
<Th>{t('support.openapi.Max usage')}</Th>
|
||||
<Th>{t('common.Expired Time')}</Th>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Th>创建时间</Th>
|
||||
<Th>最后一次使用时间</Th>
|
||||
<Th>{t('common.Create Time')}</Th>
|
||||
<Th>{t('common.Last use time')}</Th>
|
||||
<Th />
|
||||
</Tr>
|
||||
</Thead>
|
||||
@@ -158,7 +158,11 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
<Td>{usage}</Td>
|
||||
{feConfigs?.isPlus && (
|
||||
<>
|
||||
<Td>{limit?.credit && limit?.credit > -1 ? `${limit?.credit}` : '无限制'}</Td>
|
||||
<Td>
|
||||
{limit?.credit && limit?.credit > -1
|
||||
? `${limit?.credit}`
|
||||
: t('common.Unlimited')}
|
||||
</Td>
|
||||
<Td whiteSpace={'pre-wrap'}>
|
||||
{limit?.expiredTime
|
||||
? dayjs(limit?.expiredTime).format('YYYY/MM/DD\nHH:mm')
|
||||
@@ -168,7 +172,9 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
)}
|
||||
<Td whiteSpace={'pre-wrap'}>{dayjs(createTime).format('YYYY/MM/DD\nHH:mm:ss')}</Td>
|
||||
<Td whiteSpace={'pre-wrap'}>
|
||||
{lastUsedTime ? dayjs(lastUsedTime).format('YYYY/MM/DD\nHH:mm:ss') : '没有使用过'}
|
||||
{lastUsedTime
|
||||
? dayjs(lastUsedTime).format('YYYY/MM/DD\nHH:mm:ss')
|
||||
: t('common.Un used')}
|
||||
</Td>
|
||||
<Td>
|
||||
<Menu autoSelect={false} isLazy>
|
||||
@@ -229,10 +235,10 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
title={
|
||||
<Box>
|
||||
<Box fontWeight={'bold'} fontSize={'xl'}>
|
||||
新的 API 秘钥
|
||||
{t('support.openapi.New api key')}
|
||||
</Box>
|
||||
<Box fontSize={'sm'} color={'myGray.600'}>
|
||||
请保管好你的秘钥,秘钥不会再次展示~
|
||||
{t('support.openapi.New api key tip')}
|
||||
</Box>
|
||||
</Box>
|
||||
}
|
||||
@@ -359,14 +365,14 @@ function EditKeyModal({
|
||||
|
||||
<ModalFooter>
|
||||
<Button variant={'whiteBase'} mr={3} onClick={onClose}>
|
||||
{t('Cancel')}
|
||||
{t('common.Close')}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
isLoading={creating || updating}
|
||||
onClick={submitShareChat((data) => (isEdit ? onclickUpdate(data) : onclickCreate(data)))}
|
||||
>
|
||||
{t('Confirm')}
|
||||
{t('common.Confirm')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</MyModal>
|
||||
|
@@ -33,20 +33,16 @@ ${chatModelList
|
||||
md: `
|
||||
| 模型 | 价格(¥) |
|
||||
| --- | --- |
|
||||
${vectorModelList?.map((item) => `| ${item.name} | ${item.inputPrice}/1k tokens |`).join('\n')}
|
||||
${vectorModelList?.map((item) => `| ${item.name} | ${item.inputPrice}/1k 字符 |`).join('\n')}
|
||||
`
|
||||
},
|
||||
{
|
||||
title: '文件预处理模型(QA 拆分)',
|
||||
describe: '',
|
||||
md: `
|
||||
| 模型 | 输入价格(¥) | 输出价格(¥) |
|
||||
| --- | --- | --- |
|
||||
${qaModelList
|
||||
?.map(
|
||||
(item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`
|
||||
)
|
||||
.join('\n')}
|
||||
| 模型 | 价格(¥) |
|
||||
| --- | --- |
|
||||
${qaModelList?.map((item) => `| ${item.name} | ${item.inputPrice}/1k 字符 |`).join('\n')}
|
||||
`
|
||||
},
|
||||
{
|
||||
@@ -84,14 +80,6 @@ ${qgModelList
|
||||
(item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`
|
||||
)
|
||||
.join('\n')}`
|
||||
},
|
||||
{
|
||||
title: '重排模型(增强检索 & 混合检索)',
|
||||
describe: '',
|
||||
md: `
|
||||
| 模型 | 价格(¥) |
|
||||
| --- | --- |
|
||||
${reRankModelList?.map((item) => `| ${item.name} | ${item.inputPrice}/1k 字符 |`).join('\n')}`
|
||||
},
|
||||
{
|
||||
title: '语音播放',
|
||||
|
Reference in New Issue
Block a user