/*
Copyright (C) 2025 QuantumNous
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
For commercial licensing, please contact support@quantumnous.com
*/
import React from 'react';
import {
Modal,
Button,
Input,
Table,
Tag,
Typography,
Select,
} from '@douyinfe/semi-ui';
import { IconSearch } from '@douyinfe/semi-icons';
import { copy, showError, showInfo, showSuccess } from '../../../../helpers';
import { MODEL_TABLE_PAGE_SIZE } from '../../../../constants';
const ModelTestModal = ({
showModelTestModal,
currentTestChannel,
handleCloseModal,
isBatchTesting,
batchTestModels,
modelSearchKeyword,
setModelSearchKeyword,
selectedModelKeys,
setSelectedModelKeys,
modelTestResults,
testingModels,
testChannel,
modelTablePage,
setModelTablePage,
selectedEndpointType,
setSelectedEndpointType,
allSelectingRef,
isMobile,
t,
}) => {
const hasChannel = Boolean(currentTestChannel);
const filteredModels = hasChannel
? currentTestChannel.models
.split(',')
.filter((model) =>
model.toLowerCase().includes(modelSearchKeyword.toLowerCase()),
)
: [];
const endpointTypeOptions = [
{ value: '', label: t('自动检测') },
{ value: 'openai', label: 'OpenAI (/v1/chat/completions)' },
{ value: 'openai-response', label: 'OpenAI Response (/v1/responses)' },
{ value: 'anthropic', label: 'Anthropic (/v1/messages)' },
{
value: 'gemini',
label: 'Gemini (/v1beta/models/{model}:generateContent)',
},
{ value: 'jina-rerank', label: 'Jina Rerank (/rerank)' },
{
value: 'image-generation',
label: t('图像生成') + ' (/v1/images/generations)',
},
{ value: 'embeddings', label: 'Embeddings (/v1/embeddings)' },
];
const handleCopySelected = () => {
if (selectedModelKeys.length === 0) {
showError(t('请先选择模型!'));
return;
}
copy(selectedModelKeys.join(',')).then((ok) => {
if (ok) {
showSuccess(
t('已复制 ${count} 个模型').replace(
'${count}',
selectedModelKeys.length,
),
);
} else {
showError(t('复制失败,请手动复制'));
}
});
};
const handleSelectSuccess = () => {
if (!currentTestChannel) return;
const successKeys = currentTestChannel.models
.split(',')
.filter((m) => m.toLowerCase().includes(modelSearchKeyword.toLowerCase()))
.filter((m) => {
const result = modelTestResults[`${currentTestChannel.id}-${m}`];
return result && result.success;
});
if (successKeys.length === 0) {
showInfo(t('暂无成功模型'));
}
setSelectedModelKeys(successKeys);
};
const columns = [
{
title: t('模型名称'),
dataIndex: 'model',
render: (text) => (