Files

185 lines
5.2 KiB
JavaScript
Raw Permalink Normal View History

2026-03-17 14:36:31 +08:00
// LlamaFactoryTab.js 组件
import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import {
Button,
FormControlLabel,
Checkbox,
Typography,
Box,
TextField,
Alert,
CircularProgress,
IconButton,
Tooltip
} from '@mui/material';
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
import CheckIcon from '@mui/icons-material/Check';
const LlamaFactoryTab = ({
projectId,
systemPrompt,
reasoningLanguage,
confirmedOnly,
includeCOT,
formatType,
handleSystemPromptChange,
handleReasoningLanguageChange,
handleConfirmedOnlyChange,
handleIncludeCOTChange
}) => {
const { t } = useTranslation();
const [configExists, setConfigExists] = useState(false);
const [configPath, setConfigPath] = useState('');
const [generating, setGenerating] = useState(false);
const [error, setError] = useState('');
const [copied, setCopied] = useState(false);
// 检查配置文件是否存在
useEffect(() => {
if (projectId) {
fetch(`/api/projects/${projectId}/llamaFactory/checkConfig`)
.then(res => res.json())
.then(data => {
setConfigExists(data.exists);
if (data.exists) {
setConfigPath(data.configPath);
}
})
.catch(err => {
setError(err.message);
});
}
}, [projectId, configExists]);
// 复制路径到剪贴板
const handleCopyPath = () => {
const path = configPath.replace('dataset_info.json', '');
navigator.clipboard.writeText(path).then(() => {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
});
};
// 处理生成 Llama Factory 配置
const handleGenerateConfig = async () => {
try {
setGenerating(true);
setError('');
const response = await fetch(`/api/projects/${projectId}/llamaFactory/generate`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
formatType,
systemPrompt,
reasoningLanguage,
confirmedOnly,
includeCOT
})
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error);
}
setConfigExists(true);
} catch (err) {
setError(err.message);
} finally {
setGenerating(false);
}
};
return (
<Box sx={{ mt: 2 }}>
{error && (
<Alert severity="error" sx={{ mt: 2 }}>
{error}
</Alert>
)}
<Box sx={{ mb: 3 }}>
<Typography variant="subtitle1" gutterBottom>
{t('export.systemPrompt')}
</Typography>
<TextField
fullWidth
multiline
rows={3}
value={systemPrompt}
onChange={handleSystemPromptChange}
variant="outlined"
/>
</Box>
{/* Reasoning language only for multilingualthinking */}
{formatType === 'multilingualthinking' && (
<Box sx={{ mb: 3 }}>
<Typography variant="subtitle1" fontWeight="bold" gutterBottom>
{t('export.reasoningLanguage')}
</Typography>
<TextField
fullWidth
rows={3}
multiline
variant="outlined"
placeholder={t('export.reasoningLanguage')}
value={reasoningLanguage}
onChange={handleReasoningLanguageChange}
/>
</Box>
)}
<Box sx={{ mb: 2, display: 'flex', flexDirection: 'row', gap: 4 }}>
<FormControlLabel
control={<Checkbox checked={confirmedOnly} onChange={handleConfirmedOnlyChange} />}
label={t('export.onlyConfirmed')}
/>
<FormControlLabel
control={<Checkbox checked={includeCOT} onChange={handleIncludeCOTChange} />}
label={t('export.includeCOT')}
/>
</Box>
{configExists ? (
<>
<Alert severity="success" sx={{ mb: 2 }}>
{t('export.configExists')}
</Alert>
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
<Typography variant="body2" color="text.secondary">
{t('export.configPath')}: {configPath.replace('dataset_info.json', '')}
</Typography>
<Tooltip title={copied ? t('common.copied') : t('common.copy')}>
<IconButton size="small" onClick={handleCopyPath} sx={{ ml: 1 }}>
{copied ? <CheckIcon fontSize="small" color="success" /> : <ContentCopyIcon fontSize="small" />}
</IconButton>
</Tooltip>
</Box>
</>
) : (
<Typography variant="body2" color="text.secondary" gutterBottom>
{t('export.noConfig')}
</Typography>
)}
<Box sx={{ display: 'flex', justifyContent: 'flex-end', mt: 2 }}>
<Button onClick={handleGenerateConfig} variant="contained" disabled={generating} sx={{ borderRadius: 2 }}>
{generating ? (
<CircularProgress size={24} />
) : configExists ? (
t('export.updateConfig')
) : (
t('export.generateConfig')
)}
</Button>
</Box>
</Box>
);
};
export default LlamaFactoryTab;