model perf (#3657)

* fix: model

* dataset quote

* perf: model config

* model tag

* doubao model config

* perf: config model

* feat: model test
This commit is contained in:
Archer
2025-01-24 14:10:14 +08:00
committed by archer
parent f2be9ae32d
commit e48df175d7
171 changed files with 1902 additions and 3126 deletions

View File

@@ -0,0 +1,105 @@
import { eventBus, EventNameEnum } from '@/web/common/utils/eventbus';
import {
Button,
Link,
Popover,
PopoverTrigger,
PopoverContent,
PopoverHeader,
PopoverBody,
PopoverArrow,
PopoverCloseButton
} from '@chakra-ui/react';
import MyIcon from '@fastgpt/web/components/common/Icon';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { useTranslation } from 'next-i18next';
import React, { useMemo } from 'react';
import { getQuoteData } from '@/web/core/dataset/api';
import MyBox from '@fastgpt/web/components/common/MyBox';
import RawSourceBox from '../core/dataset/RawSourceBox';
import { getCollectionSourceData } from '@fastgpt/global/core/dataset/collection/utils';
import Markdown from '.';
const A = ({ children, ...props }: any) => {
const { t } = useTranslation();
const {
data: quoteData,
loading,
runAsync
} = useRequest2(getQuoteData, {
manual: true
});
// empty href link
if (!props.href && typeof children?.[0] === 'string') {
const text = useMemo(() => String(children), [children]);
return (
<MyTooltip label={t('common:core.chat.markdown.Quick Question')}>
<Button
variant={'whitePrimary'}
size={'xs'}
borderRadius={'md'}
my={1}
onClick={() => eventBus.emit(EventNameEnum.sendQuestion, { text })}
>
{text}
</Button>
</MyTooltip>
);
}
// Quote
if (props.href === 'QUOTE' && typeof children?.[0] === 'string') {
return (
<Popover
direction="rtl"
isLazy
placement="auto"
strategy={'fixed'}
onOpen={() => runAsync(String(children))}
>
<PopoverTrigger>
<Button variant={'unstyled'} minH={0} minW={0} h={'auto'}>
<MyTooltip label={t('common:read_quote')}>
<MyIcon
name={'core/chat/quoteSign'}
w={'1rem'}
color={'primary.700'}
cursor={'pointer'}
transform={'translateY(-3px)'}
/>
</MyTooltip>
</Button>
</PopoverTrigger>
<PopoverContent boxShadow={'lg'} w={'400px'}>
<MyBox isLoading={loading} minH={'300px'}>
<PopoverArrow />
<PopoverHeader h={'40px'} display={'flex'} alignItems={'center'}>
{quoteData?.collection && (
<RawSourceBox
collectionId={quoteData?.collection._id}
{...getCollectionSourceData(quoteData?.collection)}
fontSize={'sm'}
color={'black'}
textDecoration={'none'}
/>
)}
<PopoverCloseButton />
</PopoverHeader>
<PopoverBody fontSize={'sm'} maxH={'400px'} overflow={'auto'}>
<Markdown source={quoteData?.q} />
<Markdown source={quoteData?.a} />
</PopoverBody>
</MyBox>
</PopoverContent>
</Popover>
);
}
return <Link {...props}>{children}</Link>;
};
export default A;

View File

@@ -10,12 +10,7 @@ import RehypeExternalLinks from 'rehype-external-links';
import styles from './index.module.scss';
import dynamic from 'next/dynamic';
import { Link, Button, Box } from '@chakra-ui/react';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { useTranslation } from 'next-i18next';
import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { MARKDOWN_QUOTE_SIGN } from '@fastgpt/global/core/chat/constants';
import { Box } from '@chakra-ui/react';
import { CodeClassNameEnum } from './utils';
const CodeLight = dynamic(() => import('./CodeLight'), { ssr: false });
@@ -27,6 +22,7 @@ const IframeHtmlCodeBlock = dynamic(() => import('./codeBlock/iframe-html'), { s
const ChatGuide = dynamic(() => import('./chat/Guide'), { ssr: false });
const QuestionGuide = dynamic(() => import('./chat/QuestionGuide'), { ssr: false });
const A = dynamic(() => import('./A'), { ssr: false });
type Props = {
source?: string;
@@ -74,7 +70,10 @@ const MarkdownRender = ({ source = '', showAnimation, isDisabled, forbidZhFormat
'$1$3 $2$4'
)
// 处理引用标记
.replace(/\n*(\[QUOTE SIGN\]\(.*\))/g, '$1');
.replace(/\n*(\[QUOTE SIGN\]\(.*\))/g, '$1')
// 处理 [quote:id] 格式引用,将 [quote:675934a198f46329dfc6d05a] 转换为 [675934a198f46329dfc6d05a]()
.replace(/\[quote:?\s*([a-f0-9]{24})\](?!\()/gi, '[$1](QUOTE)')
.replace(/\[([a-f0-9]{24})\](?!\()/g, '[$1](QUOTE)');
// 还原 URL
const finalText = textWithSpaces.replace(
@@ -155,53 +154,6 @@ function Image({ src }: { src?: string }) {
return <MdImage src={src} />;
}
function A({ children, ...props }: any) {
const { t } = useTranslation();
// empty href link
if (!props.href && typeof children?.[0] === 'string') {
const text = useMemo(() => String(children), [children]);
return (
<MyTooltip label={t('common:core.chat.markdown.Quick Question')}>
<Button
variant={'whitePrimary'}
size={'xs'}
borderRadius={'md'}
my={1}
onClick={() => eventBus.emit(EventNameEnum.sendQuestion, { text })}
>
{text}
</Button>
</MyTooltip>
);
}
// quote link(未使用)
if (children?.length === 1 && typeof children?.[0] === 'string') {
const text = String(children);
if (text === MARKDOWN_QUOTE_SIGN && props.href) {
return (
<MyTooltip label={props.href}>
<MyIcon
name={'core/chat/quoteSign'}
transform={'translateY(-2px)'}
w={'18px'}
color={'primary.500'}
cursor={'pointer'}
_hover={{
color: 'primary.700'
}}
// onClick={() => getCollectionSourceAndOpen(props.href)}
/>
</MyTooltip>
);
}
}
return <Link {...props}>{children}</Link>;
}
function RewritePre({ children }: any) {
const modifiedChildren = React.Children.map(children, (child) => {
if (React.isValidElement(child)) {

View File

@@ -307,12 +307,11 @@ const AIChatSettingsModal = ({
)}
{showVisionSwitch && (
<Flex {...FlexItemStyles} h={'25px'}>
<Box {...LabelStyles}>
<Box {...LabelStyles} w={llmSupportVision ? '9rem' : 'auto'}>
<Flex alignItems={'center'}>
{t('app:llm_use_vision')}
<QuestionTip ml={1} label={t('app:llm_use_vision_tip')}></QuestionTip>
</Flex>
{llmSupportVision ? (
<Switch
isChecked={useVision}
@@ -323,7 +322,7 @@ const AIChatSettingsModal = ({
}}
/>
) : (
<Box fontSize={'sm'} color={'myGray.500'}>
<Box ml={3} fontSize={'sm'} color={'myGray.500'}>
{t('app:llm_not_support_vision')}
</Box>
)}

View File

@@ -82,7 +82,7 @@ const ModelTable = () => {
) : (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{item.charsPointsPrice}
{item.charsPointsPrice || 0}
</Box>
{`${t('common:support.wallet.subscription.point')} / 1K Tokens`}
</Flex>
@@ -95,7 +95,7 @@ const ModelTable = () => {
priceLabel: (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{item.charsPointsPrice}
{item.charsPointsPrice || 0}
</Box>
{` ${t('common:support.wallet.subscription.point')} / 1K Tokens`}
</Flex>
@@ -108,7 +108,7 @@ const ModelTable = () => {
priceLabel: (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{item.charsPointsPrice}
{item.charsPointsPrice || 0}
</Box>
{` ${t('common:support.wallet.subscription.point')} / 1K ${t('common:unit.character')}`}
</Flex>

View File

@@ -35,6 +35,7 @@ import {
getModelConfigJson,
getSystemModelDetail,
getSystemModelList,
getTestModel,
putSystemModel
} from '@/web/core/ai/config';
import MyBox from '@fastgpt/web/components/common/MyBox';
@@ -52,14 +53,21 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import { putUpdateWithJson } from '@/web/core/ai/config';
import CopyBox from '@fastgpt/web/components/common/String/CopyBox';
import MyIcon from '@fastgpt/web/components/common/Icon';
const MyModal = dynamic(() => import('@fastgpt/web/components/common/MyModal'));
const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
const { t } = useTranslation();
const { userInfo } = useUserStore();
const { llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList } =
useSystemStore();
const {
llmModelList,
embeddingModelList,
ttsModelList,
sttModelList,
reRankModelList,
feConfigs
} = useSystemStore();
const isRoot = userInfo?.username === 'root';
@@ -125,7 +133,7 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
) : (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{item.charsPointsPrice}
{item.charsPointsPrice || 0}
</Box>
{`${t('common:support.wallet.subscription.point')} / 1K Tokens`}
</Flex>
@@ -140,7 +148,7 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
priceLabel: (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{item.charsPointsPrice}
{item.charsPointsPrice || 0}
</Box>
{` ${t('common:support.wallet.subscription.point')} / 1K Tokens`}
</Flex>
@@ -155,7 +163,7 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
priceLabel: (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{item.charsPointsPrice}
{item.charsPointsPrice || 0}
</Box>
{` ${t('common:support.wallet.subscription.point')} / 1K ${t('common:unit.character')}`}
</Flex>
@@ -239,6 +247,10 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
);
}, [systemModelList]);
const { runAsync: onTestModel, loading: testingModel } = useRequest2(getTestModel, {
manual: true,
successToast: t('common:common.Success')
});
const { runAsync: updateModel, loading: updatingModel } = useRequest2(putSystemModel, {
onSuccess: refreshModels
});
@@ -275,8 +287,8 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
model: '',
name: '',
charsPointsPrice: 0,
inputPrice: 0,
outputPrice: 0,
inputPrice: undefined,
outputPrice: undefined,
isCustom: true,
isActive: true,
@@ -291,7 +303,9 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
onClose: onCloseJsonConfig
} = useDisclosure();
const isLoading = loadingModels || loadingData || updatingModel;
const isLoading = loadingModels || loadingData || updatingModel || testingModel;
const [showModelId, setShowModelId] = useState(true);
return (
<>
@@ -376,9 +390,20 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
<Table>
<Thead>
<Tr color={'myGray.600'}>
<Th fontSize={'xs'}>{t('common:model.name')}</Th>
<Th fontSize={'xs'}>
<HStack
spacing={1}
cursor={'pointer'}
onClick={() => setShowModelId(!showModelId)}
>
<Box>
{showModelId ? t('account:model.model_id') : t('common:model.name')}
</Box>
<MyIcon name={'modal/changePer'} w={'1rem'} />
</HStack>
</Th>
<Th fontSize={'xs'}>{t('common:model.model_type')}</Th>
<Th fontSize={'xs'}>{t('common:model.billing')}</Th>
{feConfigs?.isPlus && <Th fontSize={'xs'}>{t('common:model.billing')}</Th>}
<Th fontSize={'xs'}>
<Box
cursor={'pointer'}
@@ -396,16 +421,37 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
<Tr key={item.model} _hover={{ bg: 'myGray.50' }}>
<Td fontSize={'sm'}>
<HStack>
<Avatar src={item.avatar} w={'1.2rem'} />
<CopyBox value={item.name} color={'myGray.900'}>
{item.name}
<Avatar src={item.avatar} w={'1.2rem'} borderRadius={'50%'} />
<CopyBox
value={showModelId ? item.model : item.name}
color={'myGray.900'}
fontWeight={'500'}
>
{showModelId ? item.model : item.name}
</CopyBox>
</HStack>
<HStack mt={2}>
{item.contextToken && (
<MyTag type="borderFill" colorSchema="blue" py={0.5}>
{Math.floor(item.contextToken / 1000)}k
</MyTag>
)}
{item.vision && (
<MyTag type="borderFill" colorSchema="green" py={0.5}>
{t('account:model.vision_tag')}
</MyTag>
)}
{item.toolChoice && (
<MyTag type="borderFill" colorSchema="adora" py={0.5}>
{t('account:model.tool_choice_tag')}
</MyTag>
)}
</HStack>
</Td>
<Td>
<MyTag colorSchema={item.tagColor as any}>{item.typeLabel}</MyTag>
</Td>
<Td fontSize={'sm'}>{item.priceLabel}</Td>
{feConfigs?.isPlus && <Td fontSize={'sm'}>{item.priceLabel}</Td>}
<Td fontSize={'sm'}>
<Switch
size={'sm'}
@@ -421,8 +467,14 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
</Td>
<Td>
<HStack>
<MyIconButton
icon={'core/chat/sendLight'}
tip={t('account:model.test_model')}
onClick={() => onTestModel(item.model)}
/>
<MyIconButton
icon={'common/settingLight'}
tip={t('account:model.edit_model')}
onClick={() => onEditModel(item.model)}
/>
{item.isCustom && (
@@ -545,24 +597,6 @@ const ModelEditModal = ({
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>{t('common:model.provider')}</Td>
<Td textAlign={'right'}>
{isCustom ? (
<MySelect
value={provider}
onchange={(value) => setValue('provider', value)}
list={providerList.current}
{...InputStyles}
/>
) : (
<HStack justifyContent={'flex-end'}>
<Avatar src={providerData.avatar} w={'1rem'} />
<Box>{t(providerData.name)}</Box>
</HStack>
)}
</Td>
</Tr>
<Tr>
<Td>
<HStack spacing={1}>
@@ -578,6 +612,17 @@ const ModelEditModal = ({
)}
</Td>
</Tr>
<Tr>
<Td>{t('common:model.provider')}</Td>
<Td textAlign={'right'}>
<MySelect
value={provider}
onchange={(value) => setValue('provider', value)}
list={providerList.current}
{...InputStyles}
/>
</Td>
</Tr>
<Tr>
<Td>
<HStack spacing={1}>

View File

@@ -79,6 +79,16 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo
}>();
const quoteTemplateVariables = useMemo(
() => [
{
key: 'id',
label: 'id',
icon: 'core/app/simpleMode/variable'
},
{
key: 'source',
label: t('common:core.dataset.search.Source name'),
icon: 'core/app/simpleMode/variable'
},
{
key: 'q',
label: 'q',
@@ -90,13 +100,8 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo
icon: 'core/app/simpleMode/variable'
},
{
key: 'source',
label: t('common:core.dataset.search.Source name'),
icon: 'core/app/simpleMode/variable'
},
{
key: 'sourceId',
label: t('common:core.dataset.search.Source id'),
key: 'updateTime',
label: t('app:source_updateTime'),
icon: 'core/app/simpleMode/variable'
},
{

View File

@@ -20,6 +20,11 @@ export type listResponse = {
isActive: boolean;
isCustom: boolean;
// Tag
contextToken?: number;
vision?: boolean;
toolChoice?: boolean;
}[];
async function handler(
@@ -39,7 +44,13 @@ async function handler(
inputPrice: model.inputPrice,
outputPrice: model.outputPrice,
isActive: model.isActive ?? false,
isCustom: model.isCustom ?? false
isCustom: model.isCustom ?? false,
// Tag
contextToken:
'maxContext' in model ? model.maxContext : 'maxToken' in model ? model.maxToken : undefined,
vision: 'vision' in model ? model.vision : undefined,
toolChoice: 'toolChoice' in model ? model.toolChoice : undefined
}));
}

View File

@@ -0,0 +1,126 @@
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth';
import { findModelFromAlldata } from '@fastgpt/service/core/ai/model';
import {
EmbeddingModelItemType,
LLMModelItemType,
ReRankModelItemType,
STTModelType,
TTSModelType
} from '@fastgpt/global/core/ai/model.d';
import { getAIApi } from '@fastgpt/service/core/ai/config';
import { addLog } from '@fastgpt/service/common/system/log';
import { getVectorsByText } from '@fastgpt/service/core/ai/embedding';
import { reRankRecall } from '@fastgpt/service/core/ai/rerank';
import { aiTranscriptions } from '@fastgpt/service/core/ai/audio/transcriptions';
import { isProduction } from '@fastgpt/global/common/system/constants';
import * as fs from 'fs';
export type testQuery = { model: string };
export type testBody = {};
export type testResponse = any;
async function handler(
req: ApiRequestProps<testBody, testQuery>,
res: ApiResponseType<any>
): Promise<testResponse> {
await authSystemAdmin({ req });
const { model } = req.query;
const modelData = findModelFromAlldata(model);
if (!modelData) return Promise.reject('Model not found');
if (modelData.type === 'llm') {
return testLLMModel(modelData);
}
if (modelData.type === 'embedding') {
return testEmbeddingModel(modelData);
}
if (modelData.type === 'tts') {
return testTTSModel(modelData);
}
if (modelData.type === 'stt') {
return testSTTModel(modelData);
}
if (modelData.type === 'rerank') {
return testReRankModel(modelData);
}
return Promise.reject('Model type not supported');
}
export default NextAPI(handler);
const testLLMModel = async (model: LLMModelItemType) => {
const ai = getAIApi({});
const response = await ai.chat.completions.create(
{
model: model.model,
messages: [{ role: 'user', content: 'hi' }],
stream: false,
max_tokens: 10
},
{
...(model.requestUrl ? { path: model.requestUrl } : {}),
headers: {
...(model.requestAuth ? { Authorization: `Bearer ${model.requestAuth}` } : {})
}
}
);
const responseText = response.choices?.[0]?.message?.content;
if (!responseText) {
return Promise.reject('Model response empty');
}
addLog.info(`Model test response: ${responseText}`);
};
const testEmbeddingModel = async (model: EmbeddingModelItemType) => {
return getVectorsByText({
input: 'Hi',
model
});
};
const testTTSModel = async (model: TTSModelType) => {
const ai = getAIApi();
await ai.audio.speech.create(
{
model: model.model,
voice: model.voices[0]?.value as any,
input: 'Hi',
response_format: 'mp3',
speed: 1
},
model.requestUrl && model.requestAuth
? {
path: model.requestUrl,
headers: {
Authorization: `Bearer ${model.requestAuth}`
}
}
: {}
);
};
const testSTTModel = async (model: STTModelType) => {
const path = isProduction ? '/app/data/test.mp3' : 'data/test.mp3';
const { text } = await aiTranscriptions({
model: model.model,
fileStream: fs.createReadStream(path)
});
addLog.info(`STT result: ${text}`);
};
const testReRankModel = async (model: ReRankModelItemType) => {
await reRankRecall({
query: 'Hi',
documents: [{ id: '1', text: 'Hi' }]
});
};

View File

@@ -39,6 +39,9 @@ async function handler(
return Promise.reject(`${item.model} metadata.provider is required`);
}
item.metadata.model = item.model.trim();
if (!item.metadata.name) {
item.metadata.name = item.model;
}
}
await mongoSessionRun(async (session) => {

View File

@@ -0,0 +1,34 @@
import type { NextApiRequest } from 'next';
import { NextAPI } from '@/service/middleware/entry';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { authDatasetData } from '@fastgpt/service/support/permission/dataset/auth';
import { CollectionWithDatasetType } from '@fastgpt/global/core/dataset/type';
export type GetQuoteDataResponse = {
collection: CollectionWithDatasetType;
q: string;
a: string;
};
async function handler(req: NextApiRequest): Promise<GetQuoteDataResponse> {
const { id: dataId } = req.query as {
id: string;
};
// 凭证校验
const { datasetData, collection } = await authDatasetData({
req,
authToken: true,
authApiKey: true,
dataId,
per: ReadPermissionVal
});
return {
collection,
q: datasetData.q,
a: datasetData.a
};
}
export default NextAPI(handler);

View File

@@ -1,14 +1,12 @@
import { initHttpAgent } from '@fastgpt/service/common/middle/httpAgent';
import fs, { existsSync, readdirSync } from 'fs';
import fs, { existsSync } from 'fs';
import type { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types/index.d';
import type { FastGPTConfigFileType } from '@fastgpt/global/common/system/types/index.d';
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
import { getFastGPTConfigFromDB } from '@fastgpt/service/common/system/config/controller';
import { FastGPTProUrl } from '@fastgpt/service/common/system/constants';
import { isProduction } from '@fastgpt/global/common/system/constants';
import { initFastGPTConfig } from '@fastgpt/service/common/system/tools';
import json5 from 'json5';
import { SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type';
import { defaultGroup, defaultTemplateTypes } from '@fastgpt/web/core/workflow/constants';
import { MongoPluginGroups } from '@fastgpt/service/core/app/plugin/pluginGroupSchema';
import { MongoTemplateTypes } from '@fastgpt/service/core/app/templates/templateTypeSchema';
@@ -48,14 +46,7 @@ export function initGlobalVariables() {
/* Init system data(Need to connected db). It only needs to run once */
export async function getInitConfig() {
return Promise.all([
initSystemConfig(),
getSystemVersion(),
loadSystemModels(),
// abandon
getSystemPlugin()
]);
return Promise.all([initSystemConfig(), getSystemVersion(), loadSystemModels()]);
}
const defaultFeConfigs: FastGPTFeConfigsType = {
@@ -129,34 +120,6 @@ async function getSystemVersion() {
}
}
async function getSystemPlugin() {
if (global.communityPlugins && global.communityPlugins.length > 0) return;
const basePath =
process.env.NODE_ENV === 'development' ? 'data/pluginTemplates' : '/app/data/pluginTemplates';
// read data/pluginTemplates directory, get all json file
const files = readdirSync(basePath);
// filter json file
const filterFiles = files.filter((item) => item.endsWith('.json'));
// read json file
const fileTemplates = await Promise.all(
filterFiles.map<Promise<SystemPluginTemplateItemType>>(async (filename) => {
const content = await fs.promises.readFile(`${basePath}/${filename}`, 'utf-8');
return {
...json5.parse(content),
originCost: 0,
currentCost: 0,
id: `${PluginSourceEnum.community}-${filename.replace('.json', '')}`
};
})
);
fileTemplates.sort((a, b) => (b.weight || 0) - (a.weight || 0));
global.communityPlugins = fileTemplates;
}
export async function initSystemPluginGroups() {
try {
const { groupOrder, ...restDefaultGroup } = defaultGroup;

View File

@@ -1,4 +1,4 @@
import { GET, PUT, DELETE } from '@/web/common/api/request';
import { GET, PUT, DELETE, POST } from '@/web/common/api/request';
import type { listResponse } from '@/pages/api/core/ai/model/list';
import type { updateBody } from '@/pages/api/core/ai/model/update';
import type { deleteQuery } from '@/pages/api/core/ai/model/delete';
@@ -16,3 +16,5 @@ export const deleteSystemModel = (data: deleteQuery) => DELETE('/core/ai/model/d
export const getModelConfigJson = () => GET<string>('/core/ai/model/getConfigJson');
export const putUpdateWithJson = (data: updateWithJsonBody) =>
PUT('/core/ai/model/updateWithJson', data);
export const getTestModel = (model: String) => GET('/core/ai/model/test', { model });

View File

@@ -65,6 +65,7 @@ import type {
listExistIdQuery,
listExistIdResponse
} from '@/pages/api/core/dataset/apiDataset/listExistId';
import { GetQuoteDataResponse } from '@/pages/api/core/dataset/data/getQuoteData';
/* ======================== dataset ======================= */
export const getDatasets = (data: GetDatasetListBody) =>
@@ -203,6 +204,10 @@ export const putDatasetDataById = (data: UpdateDatasetDataProps) =>
export const delOneDatasetDataById = (id: string) =>
DELETE<string>(`/core/dataset/data/delete`, { id });
// Get quote data
export const getQuoteData = (id: string) =>
GET<GetQuoteDataResponse>(`/core/dataset/data/getQuoteData`, { id });
/* ================ training ==================== */
export const postRebuildEmbedding = (data: rebuildEmbeddingBody) =>
POST(`/core/dataset/training/rebuildEmbedding`, data);