import { useState, memo } from 'react' import api, { ModelInfo } from '../api/client' const ModelRow = memo(function ModelRow({ m, onTest, onDelete }: { m: ModelInfo onTest: (id: string) => void onDelete: (id: string, name: string) => void }) { return ( { e.currentTarget.style.background = '#fafbfc' }} onMouseLeave={e => { e.currentTarget.style.background = 'transparent' }} > {m.id} {m.name} {m.model_type} {m.is_downloaded ? '已缓存' : '未下载'} {m.supported_peft_methods.join(', ') || '-'} {m.is_downloaded && ( )} ) }) export function Models() { const [modelId, setModelId] = useState('') const [useModelscope, setUseModelscope] = useState(false) const [downloading, setDownloading] = useState(false) const [models, setModels] = useState([]) const [loading, setLoading] = useState(false) const [statusMsg, setStatusMsg] = useState('') // Test state const [testModelId, setTestModelId] = useState('') const [testPrompt, setTestPrompt] = useState('') const [testResult, setTestResult] = useState('') const [testError, setTestError] = useState('') const [testing, setTesting] = useState(false) const fetchModels = () => { setLoading(true) api.models.list() .then(setModels) .catch(() => setModels([])) .finally(() => setLoading(false)) } const handleDownload = () => { if (!modelId.trim()) return setDownloading(true) setStatusMsg('正在下载...') api.models.download(modelId, useModelscope) .then(res => setStatusMsg(`✅ ${res.model_id}: ${res.status}`)) .catch(err => setStatusMsg(`❌ 下载失败: ${err.message}`)) .finally(() => setDownloading(false)) } const handleDelete = async (id: string, name: string) => { if (!confirm(`确定删除模型 "${name}"?这将删除本地所有相关文件。`)) return try { await api.models.delete(id) fetchModels() } catch (err) { const msg = err instanceof Error ? err.message : '删除失败' setStatusMsg(`❌ ${msg}`) } } const handleTest = async (id: string) => { setTestModelId(id) setTestPrompt('') setTestResult('') setTestError('') // Show test panel setTestPrompt('你好,请简单介绍一下自己。') } const handleTestSubmit = async () => { if (!testModelId.trim() || !testPrompt.trim()) return setTesting(true) setTestResult('') setTestError('') try { const res = await api.models.test({ model_id: testModelId, prompt: testPrompt, max_new_tokens: 128, temperature: 0.8, top_p: 0.95, }) setTestResult(res.generated_text) } catch (err) { const msg = err instanceof Error ? err.message : '测试失败' setTestError(msg) } finally { setTesting(false) } } return (

模型注册

下载和管理预训练模型

{/* Download form */}

下载模型

setModelId(e.target.value)} style={{ padding: '10px 14px', flex: 1, maxWidth: 400, borderRadius: 8, border: '1px solid #d0d0d0', fontSize: 14, outline: 'none', transition: 'border-color 0.2s', }} onFocus={e => { e.currentTarget.style.borderColor = '#e94560' }} onBlur={e => { e.currentTarget.style.borderColor = '#d0d0d0' }} />
{statusMsg && (

{statusMsg}

)}
{/* Model list */}

已缓存模型

{loading &&

加载中...

} {!loading && models.length === 0 && (
🧠
暂无已缓存模型,请在上方下载模型
)} {!loading && models.length > 0 && (
{models.map(m => ( ))}
ID 名称 类型 状态 PEFT 支持 操作
)}
{/* Test Panel */} {testModelId && (

模型测试 — {testModelId}

{/* Chat-like input */}
setTestPrompt(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') handleTestSubmit() }} placeholder="输入提示词,按 Enter 发送..." style={{ flex: 1, padding: '10px 14px', borderRadius: 8, border: '1px solid #d0d0d0', fontSize: 14, outline: 'none', transition: 'border-color 0.2s', }} onFocus={e => { e.currentTarget.style.borderColor = '#2196f3' }} onBlur={e => { e.currentTarget.style.borderColor = '#d0d0d0' }} />
{/* Error */} {testError && (
{testError}
)} {/* Result */} {testResult && (
Prompt
{testPrompt}
Response
{testResult}
)}
)}
) }