This commit is contained in:
Archer
2023-12-31 14:12:51 +08:00
committed by GitHub
parent ccca0468da
commit 9ccfda47b7
270 changed files with 8182 additions and 1295 deletions

View File

@@ -151,7 +151,7 @@ export const QuoteList = React.memo(function QuoteList({
{item.q.length + (item.a?.length || 0)}
</Flex>
</MyTooltip>
{!isShare && item.score && (
{/* {!isShare && item.score && (
<MyTooltip label={t('core.dataset.Similarity')}>
<Flex alignItems={'center'}>
<MyIcon name={'kbTest'} w={'12px'} />
@@ -167,7 +167,7 @@ export const QuoteList = React.memo(function QuoteList({
<Box>{item.score.toFixed(4)}</Box>
</Flex>
</MyTooltip>
)}
)} */}
<Box flex={1} />
{item.id && (
<MyTooltip label={t('core.dataset.data.Edit')}>

View File

@@ -205,9 +205,9 @@ const ResponseTags = ({
</Tag>
</MyTooltip>
)}
<MyTooltip label={'点击查看完整响应'}>
<MyTooltip label={t('core.chat.response.Read complete response tips')}>
<Tag colorSchema="gray" cursor={'pointer'} {...TagStyles} onClick={onOpenWholeModal}>
{t('chat.Complete Response')}
{t('core.chat.response.Read complete response')}
</Tag>
</MyTooltip>

View File

@@ -8,7 +8,7 @@ import Tabs from '../Tabs';
import MyModal from '../MyModal';
import MyTooltip from '../MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
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';
@@ -19,7 +19,7 @@ function Row({
rawDom
}: {
label: string;
value?: string | number;
value?: string | number | boolean;
rawDom?: React.ReactNode;
}) {
const { t } = useTranslation();
@@ -70,7 +70,7 @@ const WholeResponseModal = ({
iconSrc="/imgs/modal/wholeRecord.svg"
title={
<Flex alignItems={'center'}>
{t('chat.Complete Response')}
{t('core.chat.response.Complete Response')}
<MyTooltip label={'从左往右,为各个模块的响应顺序'}>
<QuestionOutlineIcon ml={2} />
</MyTooltip>
@@ -133,15 +133,16 @@ const ResponseBox = React.memo(function ResponseBox({
{activeModule?.price !== undefined && (
<Row
label={t('core.chat.response.module price')}
value={`${formatPrice(activeModule?.price)}`}
value={`${formatStorePrice2Read(activeModule?.price)}`}
/>
)}
<Row
label={t('core.chat.response.module time')}
value={`${activeModule?.runningTime || 0}s`}
/>
<Row label={t('core.chat.response.module tokens')} value={`${activeModule?.tokens}`} />
<Row label={t('core.chat.response.module model')} value={activeModule?.model} />
<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} />
<Row
label={t('core.chat.response.context total length')}
@@ -193,6 +194,10 @@ const ResponseBox = React.memo(function ResponseBox({
)}
<Row label={t('core.chat.response.module similarity')} value={activeModule?.similarity} />
<Row label={t('core.chat.response.module limit')} value={activeModule?.limit} />
<Row
label={t('core.chat.response.search using reRank')}
value={activeModule?.searchUsingReRank}
/>
{/* classify question */}
<Row

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1703840539554" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7163" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M224.63064 14.207408h566.760385a4.266489 4.266489 0 0 1 4.735803 4.735803v227.915837a4.266489 4.266489 0 0 1-4.735803 4.735802H224.63064a4.266489 4.266489 0 0 1-4.735802-4.735802V18.943211a4.266489 4.266489 0 0 1 4.735802-4.735803z" fill="#4A8BFD" p-id="7164"></path><path d="M781.876755 28.414816v209.057956H234.059581v-209.057956h547.817174M791.34836 0H224.417316a18.943211 18.943211 0 0 0-18.943211 18.943211v227.915837a18.943211 18.943211 0 0 0 18.943211 18.94321h566.760385a18.943211 18.943211 0 0 0 18.943211-18.94321V18.943211a18.943211 18.943211 0 0 0-18.772552-18.943211z" fill="#333333" p-id="7165"></path><path d="M224.63064 393.028957h566.760385a4.266489 4.266489 0 0 1 4.735803 4.735803v227.915837a4.266489 4.266489 0 0 1-4.735803 4.735802H224.63064a4.266489 4.266489 0 0 1-4.735802-4.735802V397.76476a4.266489 4.266489 0 0 1 4.735802-4.735803z" fill="#EDEDED" p-id="7166"></path><path d="M781.876755 407.535019v208.503313H234.059581V407.535019h547.817174m9.471605-28.414816H224.417316a18.943211 18.943211 0 0 0-18.943211 18.943211v227.446523a18.943211 18.943211 0 0 0 18.943211 18.943211h566.760385a18.943211 18.943211 0 0 0 18.943211-18.943211V398.063414a18.943211 18.943211 0 0 0-18.772552-18.943211z" fill="#333333" p-id="7167"></path><path d="M224.63064 771.935836h566.760385a4.266489 4.266489 0 0 1 4.735803 4.735803v227.958501a4.266489 4.266489 0 0 1-4.735803 4.735803H224.63064a4.266489 4.266489 0 0 1-4.735802-4.735803v-227.958501a4.266489 4.266489 0 0 1 4.735802-4.735803z" fill="#4A8BFD" p-id="7168"></path><path d="M781.876755 786.185909v209.057956H234.059581v-209.057956h547.817174m9.471605-28.414816H224.417316a18.943211 18.943211 0 0 0-18.943211 18.943211v227.915836a18.943211 18.943211 0 0 0 18.943211 18.943211h566.760385a18.943211 18.943211 0 0 0 18.943211-18.943211v-227.915836a18.943211 18.943211 0 0 0-18.772552-18.943211z m56.573643-251.722845a14.207408 14.207408 0 1 1 0-28.414816 147.577851 147.577851 0 0 0 0-295.113037 14.207408 14.207408 0 1 1 0-28.414816 175.992667 175.992667 0 0 1 0 351.985334z" fill="#333333" p-id="7169"></path><path d="M884.443148 530.751219a14.122078 14.122078 0 0 1-7.295696-2.00525l-41.512937-24.916295a14.207408 14.207408 0 0 1-1.791925-23.2097l41.512937-33.150619a14.207408 14.207408 0 0 1 17.705929 22.185743l-25.598934 20.393817 23.977668 14.420732a14.207408 14.207408 0 0 1-7.295696 26.452231z m-708.237157 326.215741a175.992667 175.992667 0 0 1 0-351.985334 14.207408 14.207408 0 0 1 0 28.414816 147.577851 147.577851 0 1 0 0 295.113037 14.207408 14.207408 0 0 1 0 28.414816z" fill="#333333" p-id="7170"></path><path d="M139.428857 881.413941a14.207408 14.207408 0 0 1-7.295696-26.452231l23.977668-14.420733-25.598934-20.393816a14.207408 14.207408 0 0 1 17.705929-22.185743l41.043623 33.662598a14.207408 14.207408 0 0 1-1.621265 23.295029l-41.512937 24.916295a14.079413 14.079413 0 0 1-6.698388 1.578601z" fill="#333333" p-id="7171"></path></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1703750094429"
class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4262"
xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128">
<path
d="M512 0C229.312 0 0 229.312 0 512s229.312 512 512 512 512-229.312 512-512-229.312-512-512-512z m311.04 823.04a437.76 437.76 0 0 1-139.84 94.336c-54.208 23.04-111.808 34.624-171.2 34.624a439.36 439.36 0 0 1-311.04-128.896 437.76 437.76 0 0 1-94.336-139.904A435.776 435.776 0 0 1 72 512a439.36 439.36 0 0 1 128.896-311.04 437.76 437.76 0 0 1 139.904-94.336A435.776 435.776 0 0 1 512 72a439.36 439.36 0 0 1 311.04 128.896 437.76 437.76 0 0 1 94.336 139.904c23.04 54.208 34.624 111.808 34.624 171.2 0 59.392-11.584 116.992-34.56 171.2a436.096 436.096 0 0 1-94.336 139.904z"
p-id="4263"></path>
<path
d="M701.824 436.992h-167.04c0.704 0 1.408-0.32 2.112-1.024l118.208-117.76a35.904 35.904 0 0 0-50.816-50.56L511.872 360.064l-92.864-92.8a36.16 36.16 0 0 0-51.136 0.192 36.16 36.16 0 0 0-0.064 51.072l118.208 118.08c0.64 0.704 1.408 1.728 2.112 1.728H321.6a34.688 34.688 0 0 0-34.304 34.56v3.2c0 18.816 15.488 33.856 34.304 33.856h154.368v64H353.536c-18.752 0-33.472 16.256-33.472 35.072v4.032c0 18.752 14.72 32.896 33.472 32.896h122.56v149.184a35.968 35.968 0 1 0 72 0v-149.184h121.792c18.752 0 35.2-14.08 35.2-32.896v-4.032a35.968 35.968 0 0 0-35.2-35.072H548.032v-64h153.792c18.752 0 35.2-14.208 35.2-33.088v-4.032a36.672 36.672 0 0 0-35.2-35.84z"
p-id="4264"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -113,8 +113,8 @@ const iconPaths = {
'core/chat/speaking': () => import('./icons/core/chat/speaking.svg'),
'core/chat/fileSelect': () => import('./icons/core/chat/fileSelect.svg'),
'core/dataset/modeEmbedding': () => import('./icons/core/dataset/modeEmbedding.svg'),
'core/dataset/modeEmbeddingRerank': () => import('./icons/core/dataset/modeEmbeddingRerank.svg'),
'core/dataset/modeEmbFTRerank': () => import('./icons/core/dataset/modeEmbFTRerank.svg'),
'core/dataset/fullTextRecall': () => import('./icons/core/dataset/fullTextRecall.svg'),
'core/dataset/mixedRecall': () => import('./icons/core/dataset/mixedRecall.svg'),
'core/app/variable/input': () => import('./icons/core/app/variable/input.svg'),
'core/app/variable/textarea': () => import('./icons/core/app/variable/textarea.svg'),
'core/app/variable/select': () => import('./icons/core/app/variable/select.svg'),
@@ -125,7 +125,9 @@ const iconPaths = {
'common/confirm/commonTip': () => import('./icons/common/confirm/commonTip.svg'),
'common/routePushLight': () => import('./icons/common/routePushLight.svg'),
'common/viewLight': () => import('./icons/common/viewLight.svg'),
'core/app/customFeedback': () => import('./icons/core/app/customFeedback.svg')
'core/app/customFeedback': () => import('./icons/core/app/customFeedback.svg'),
'support/pay/priceLight': () => import('./icons/support/pay/priceLight.svg'),
'core/dataset/rerank': () => import('./icons/core/dataset/rerank.svg')
};
export type IconName = keyof typeof iconPaths;

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { useRouter } from 'next/router';
import { useToast } from '@chakra-ui/react';
import { useUserStore } from '@/web/support/user/useUserStore';

View File

@@ -218,6 +218,9 @@
.markdown blockquote > *:last-child {
margin-bottom: 0;
}
.markdown table {
width: 100%;
}
.markdown table th {
font-weight: bold;
}

View File

@@ -0,0 +1,44 @@
import React, { useMemo } from 'react';
import MySelect, { type SelectProps } from './index';
import { useTranslation } from 'next-i18next';
import dynamic from 'next/dynamic';
import { useDisclosure } from '@chakra-ui/react';
const PriceBox = dynamic(() => import('@/components/support/wallet/Price'));
const SelectAiModel = ({ list, ...props }: SelectProps) => {
const { t } = useTranslation();
const expandList = useMemo(
() =>
list.concat({
label: t('support.user.Price'),
value: 'price'
}),
[list, t]
);
const {
isOpen: isOpenPriceBox,
onOpen: onOpenPriceBox,
onClose: onClosePriceBox
} = useDisclosure();
return (
<>
<MySelect
list={expandList}
{...props}
onchange={(e) => {
if (e === 'price') {
onOpenPriceBox();
return;
}
props.onchange?.(e);
}}
/>
{isOpenPriceBox && <PriceBox onClose={onClosePriceBox} />}
</>
);
};
export default SelectAiModel;

View File

@@ -1,17 +1,9 @@
import React, { useRef, forwardRef, useMemo } from 'react';
import {
Menu,
Box,
MenuList,
MenuItem,
Button,
useDisclosure,
useOutsideClick,
MenuButton
} from '@chakra-ui/react';
import { Menu, MenuList, MenuItem, Button, useDisclosure, MenuButton } from '@chakra-ui/react';
import type { ButtonProps } from '@chakra-ui/react';
import { ChevronDownIcon } from '@chakra-ui/icons';
interface Props extends ButtonProps {
export type SelectProps = ButtonProps & {
value?: string;
placeholder?: string;
list: {
@@ -20,10 +12,10 @@ interface Props extends ButtonProps {
value: string;
}[];
onchange?: (val: any) => void;
}
};
const MySelect = (
{ placeholder, value, width = '100%', list, onchange, ...props }: Props,
{ placeholder, value, width = '100%', list, onchange, ...props }: SelectProps,
selectRef: any
) => {
const ref = useRef<HTMLButtonElement>(null);

View File

@@ -53,7 +53,7 @@ const SideTabs = ({ list, size = 'md', activeId, onChange, ...props }: Props) =>
cursor: 'pointer'
})}
_hover={{
bg: 'myWhite.600'
bg: 'myGray.05'
}}
onClick={() => {
if (activeId === item.id) return;

View File

@@ -1,5 +1,15 @@
import React, { useMemo, useState } from 'react';
import { Box, Button, ModalBody, ModalFooter, Textarea } from '@chakra-ui/react';
import {
Box,
Button,
Checkbox,
Divider,
Flex,
ModalBody,
ModalFooter,
Textarea,
useTheme
} from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import MySlider from '@/components/Slider';
@@ -12,43 +22,58 @@ import { reRankModelList } from '@/web/common/system/staticData';
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
import { DatasetSearchModeMap } from '@fastgpt/global/core/dataset/constant';
import MyRadio from '@/components/common/MyRadio';
import MyIcon from '@/components/Icon';
type DatasetParamsProps = {
similarity?: number;
limit?: number;
searchMode: `${DatasetSearchModeEnum}`;
searchEmptyText?: string;
limit?: number;
similarity?: number;
usingReRank?: boolean;
maxTokens?: number;
};
const DatasetParamsModal = ({
searchMode = DatasetSearchModeEnum.embedding,
searchEmptyText,
limit,
similarity,
searchMode = DatasetSearchModeEnum.embedding,
usingReRank,
maxTokens = 3000,
onClose,
onSuccess
}: DatasetParamsProps & { onClose: () => void; onSuccess: (e: DatasetParamsProps) => void }) => {
const { t } = useTranslation();
const theme = useTheme();
const [refresh, setRefresh] = useState(false);
const { register, setValue, getValues, handleSubmit } = useForm<DatasetParamsProps>({
defaultValues: {
searchEmptyText,
limit,
similarity,
searchMode
searchMode,
usingReRank
}
});
const searchModeList = useMemo(() => {
const list = Object.values(DatasetSearchModeMap);
if (reRankModelList.length > 0) {
return list;
}
return list.slice(0, 1);
return list;
}, []);
const showSimilarity = useMemo(() => {
if (similarity === undefined) return false;
if (
getValues('searchMode') === DatasetSearchModeEnum.fullTextRecall &&
!getValues('usingReRank')
)
return false;
if (getValues('searchMode') === DatasetSearchModeEnum.mixedRecall && !getValues('usingReRank'))
return false;
return true;
}, [getValues, similarity, refresh]);
return (
<MyModal
isOpen={true}
@@ -57,7 +82,6 @@ const DatasetParamsModal = ({
title={t('core.dataset.search.Dataset Search Params')}
w={['90vw', '550px']}
h={['90vh', 'auto']}
overflow={'unset'}
isCentered={searchEmptyText !== undefined}
>
<ModalBody flex={['1 0 0', 'auto']} overflow={'auto'}>
@@ -71,9 +95,73 @@ const DatasetParamsModal = ({
setRefresh(!refresh);
}}
/>
{usingReRank !== undefined && reRankModelList.length > 0 && (
<>
<Divider my={4} />
<Flex
alignItems={'center'}
cursor={'pointer'}
userSelect={'none'}
py={3}
pl={'14px'}
pr={'16px'}
border={theme.borders.sm}
borderWidth={'1.5px'}
borderRadius={'md'}
position={'relative'}
{...(getValues('usingReRank')
? {
borderColor: 'primary.400'
}
: {})}
onClick={(e) => {
setValue('usingReRank', !getValues('usingReRank'));
setRefresh((state) => !state);
}}
>
<MyIcon name="core/dataset/rerank" w={'18px'} mr={'14px'} />
<Box pr={2} color={'myGray.800'} flex={'1 0 0'}>
<Box>{t('core.dataset.search.ReRank')}</Box>
<Box fontSize={['xs', 'sm']} color={'myGray.500'}>
{t('core.dataset.search.ReRank desc')}
</Box>
</Box>
<Box position={'relative'} w={'18px'} h={'18px'}>
<Checkbox colorScheme="primary" isChecked={getValues('usingReRank')} size="lg" />
<Box position={'absolute'} top={0} right={0} bottom={0} left={0} zIndex={1}></Box>
</Box>
</Flex>
</>
)}
{similarity !== undefined && (
{limit !== undefined && (
<Box display={['block', 'flex']} py={8} mt={3}>
<Box flex={'0 0 100px'} mb={[8, 0]}>
{t('core.dataset.search.Max Tokens')}
<MyTooltip label={t('core.dataset.search.Max Tokens Tips')} forceShow>
<QuestionOutlineIcon ml={1} />
</MyTooltip>
</Box>
<Box flex={1} mx={4}>
<MySlider
markList={[
{ label: '100', value: 100 },
{ label: maxTokens, value: maxTokens }
]}
min={100}
max={maxTokens}
step={50}
value={getValues(ModuleInputKeyEnum.datasetLimit) ?? 1000}
onChange={(val) => {
setValue(ModuleInputKeyEnum.datasetLimit, val);
setRefresh(!refresh);
}}
/>
</Box>
</Box>
)}
{showSimilarity && (
<Box display={['block', 'flex']} py={8}>
<Box flex={'0 0 100px'} mb={[8, 0]}>
{t('core.dataset.search.Min Similarity')}
<MyTooltip label={t('core.dataset.search.Min Similarity Tips')} forceShow>
@@ -98,32 +186,7 @@ const DatasetParamsModal = ({
</Box>
</Box>
)}
{limit !== undefined && (
<Box display={['block', 'flex']} py={8}>
<Box flex={'0 0 100px'} mb={[8, 0]}>
{t('core.dataset.search.Max Tokens')}
<MyTooltip label={t('core.dataset.search.Max Tokens Tips')} forceShow>
<QuestionOutlineIcon ml={1} />
</MyTooltip>
</Box>
<Box flex={1} mx={4}>
<MySlider
markList={[
{ label: '300', value: 300 },
{ label: maxTokens, value: maxTokens }
]}
min={300}
max={maxTokens}
step={10}
value={getValues(ModuleInputKeyEnum.datasetLimit) ?? 1000}
onChange={(val) => {
setValue(ModuleInputKeyEnum.datasetLimit, val);
setRefresh(!refresh);
}}
/>
</Box>
</Box>
)}
{searchEmptyText !== undefined && (
<Box display={['block', 'flex']} pt={3}>
<Box flex={'0 0 100px'} mb={[2, 0]}>

View File

@@ -8,7 +8,7 @@ import MySelect from '@/components/Select';
import { TTSTypeEnum } from '@/constants/app';
import type { AppTTSConfigType } from '@fastgpt/global/core/module/type.d';
import { useAudioPlay } from '@/web/common/utils/voice';
import { audioSpeechModels } from '@/web/common/system/staticData';
import { audioSpeechModelList } from '@/web/common/system/staticData';
import MyModal from '@/components/MyModal';
import MySlider from '@/components/Slider';
@@ -26,7 +26,7 @@ const TTSSelect = ({
() => [
{ label: t('core.app.tts.Close'), value: TTSTypeEnum.none },
{ label: t('core.app.tts.Web'), value: TTSTypeEnum.web },
...audioSpeechModels.map((item) => item?.voices || []).flat()
...audioSpeechModelList.map((item) => item?.voices || []).flat()
],
[t]
);
@@ -52,7 +52,7 @@ const TTSSelect = ({
if (e === TTSTypeEnum.none || e === TTSTypeEnum.web) {
onChange({ type: e as `${TTSTypeEnum}` });
} else {
const audioModel = audioSpeechModels.find(
const audioModel = audioSpeechModelList.find(
(item) => item.voices?.find((voice) => voice.value === e)
);
if (!audioModel) {

View File

@@ -1,10 +1,9 @@
import React, { useCallback, useEffect } from 'react';
import type { RenderInputProps } from '../type';
import { onChangeNode } from '../../../../FlowProvider';
import MySelect from '@/components/Select';
import SelectAiModel from '@/components/Select/SelectAiModel';
import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/module/node/constant';
import { chatModelList, cqModelList, extractModelList } from '@/web/common/system/staticData';
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
const SelectAiModelRender = ({ item, inputs = [], moduleId }: RenderInputProps) => {
const modelList = (() => {
@@ -16,8 +15,7 @@ const SelectAiModelRender = ({ item, inputs = [], moduleId }: RenderInputProps)
})().map((item) => ({
model: item.model,
name: item.name,
maxResponse: item.maxResponse,
price: item.price
maxResponse: item.maxResponse
}));
const onChangeModel = useCallback(
@@ -55,11 +53,9 @@ const SelectAiModelRender = ({ item, inputs = [], moduleId }: RenderInputProps)
);
const list = modelList.map((item) => {
const priceStr = `(${formatPrice(item.price, 1000)}元/1k Tokens)`;
return {
value: item.model,
label: `${item.name}${priceStr}`
label: item.name
};
});
@@ -70,7 +66,7 @@ const SelectAiModelRender = ({ item, inputs = [], moduleId }: RenderInputProps)
}, [item.value, list, onChangeModel]);
return (
<MySelect
<SelectAiModel
minW={'350px'}
width={'100%'}
value={item.value}

View File

@@ -17,7 +17,8 @@ const SelectDatasetParam = ({ inputs = [], moduleId }: RenderInputProps) => {
const [data, setData] = useState({
searchMode: DatasetSearchModeEnum.embedding,
limit: 5,
similarity: 0.5
similarity: 0.5,
usingReRank: false
});
const tokenLimit = useMemo(() => {

View File

@@ -72,7 +72,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
} = useQuery(['getOpenApiKeys', appId], () => getOpenApiKeys({ appId }));
useEffect(() => {
setBaseUrl(`${location.origin}/api`);
setBaseUrl(feConfigs?.customApiDomain || `${location.origin}/api`);
}, []);
return (
@@ -255,7 +255,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
</ModalBody>
<ModalFooter>
<Button variant="whiteBase" onClick={() => setApiKey('')}>
{t('common.OK')}
</Button>
</ModalFooter>
</MyModal>

View File

@@ -0,0 +1,168 @@
import React from 'react';
import { Box, CloseButton } from '@chakra-ui/react';
import {
chatModelList,
vectorModelList,
qaModelList,
cqModelList,
extractModelList,
qgModelList,
audioSpeechModelList,
reRankModelList,
whisperModel
} from '@/web/common/system/staticData';
import ReactDOM from 'react-dom';
import Markdown from '@/components/Markdown';
const Price = ({ onClose }: { onClose: () => void }) => {
const list = [
{
title: '知识库存储',
describe: '',
md: `
| 计费项 | 价格(¥) |
| --- | --- |
| 知识库索引数量 | 0/1000条/天 |`
},
{
title: '对话模型',
describe: '',
md: `
| 模型 | 输入价格(¥) | 输出价格(¥) |
| --- | --- | --- |
${chatModelList
?.map((item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`)
.join('\n')}`
},
{
title: '索引模型(文档训练 & 文档检索)',
describe: '',
md: `
| 模型 | 价格(¥) |
| --- | --- |
${vectorModelList?.map((item) => `| ${item.name} | ${item.inputPrice}/1k tokens |`).join('\n')}
`
},
{
title: '文件预处理模型(QA 拆分)',
describe: '',
md: `
| 模型 | 输入价格(¥) | 输出价格(¥) |
| --- | --- | --- |
${qaModelList
?.map(
(item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`
)
.join('\n')}
`
},
{
title: '问题分类',
describe: '',
md: `
| 模型 | 输入价格(¥) | 输出价格(¥) |
| --- | --- | --- |
${cqModelList
?.map(
(item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`
)
.join('\n')}`
},
{
title: '内容提取',
describe: '',
md: `
| 模型 | 输入价格(¥) | 输出价格(¥) |
| --- | --- | --- |
${extractModelList
?.map(
(item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`
)
.join('\n')}`
},
{
title: '下一步指引',
describe: '',
md: `
| 模型 | 输入价格(¥) | 输出价格(¥) |
| --- | --- | --- |
${qgModelList
?.map(
(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: '语音播放',
describe: '',
md: `
| 模型 | 价格(¥) |
| --- | --- |
${audioSpeechModelList
?.map((item) => `| ${item.name} | ${item.inputPrice}/1k 字符 | - |`)
.join('\n')}`
},
...(whisperModel
? [
{
title: '语音输入',
describe: '',
md: `
| 模型 | 价格(¥) |
| --- | --- |
| ${whisperModel.name} | ${whisperModel.inputPrice}/分钟 | - |`
}
]
: [])
];
return ReactDOM.createPortal(
<Box position={'fixed'} top={0} right={0} bottom={0} left={0} zIndex={99999} bg={'white'}>
<CloseButton
position={'absolute'}
top={'10px'}
right={'20px'}
bg={'myGray.200'}
w={'30px'}
h={'30px'}
borderRadius={'50%'}
onClick={onClose}
/>
<Box py={[0, 10]} px={[5, '50px']} overflow={'overlay'} h={'100%'}>
{list.map((item) => (
<Box
display={['block', 'flex']}
key={item.title}
w={'100%'}
mb={4}
pb={6}
_notLast={{
borderBottom: '1px',
borderBottomColor: 'borderColor.high'
}}
>
<Box fontSize={'xl'} fontWeight={'bold'} mb={1} flex={'1 0 0'}>
{item.title}
</Box>
<Box w={['100%', '410px']}>
<Markdown source={item.md}></Markdown>
</Box>
</Box>
))}
</Box>
</Box>,
// @ts-ignore
document.querySelector('body')
);
};
export default Price;