|
|
@@ -9,6 +9,13 @@ export function Models() {
|
|
|
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()
|
|
|
@@ -38,6 +45,37 @@ export function Models() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ 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 (
|
|
|
<div>
|
|
|
<h1>模型注册</h1>
|
|
|
@@ -104,6 +142,9 @@ export function Models() {
|
|
|
</td>
|
|
|
<td>{m.supported_peft_methods.join(', ') || '-'}</td>
|
|
|
<td>
|
|
|
+ {m.is_downloaded && (
|
|
|
+ <button onClick={() => handleTest(m.id)} style={{ marginRight: 8, padding: '2px 8px', color: '#2196f3', border: '1px solid #2196f3', borderRadius: 4, background: 'transparent', cursor: 'pointer' }}>测试</button>
|
|
|
+ )}
|
|
|
<button onClick={() => handleDelete(m.id, m.name)} style={{ padding: '2px 8px', color: '#e94560', border: '1px solid #e94560', borderRadius: 4, background: 'transparent', cursor: 'pointer' }}>删除</button>
|
|
|
</td>
|
|
|
</tr>
|
|
|
@@ -112,6 +153,59 @@ export function Models() {
|
|
|
</table>
|
|
|
)}
|
|
|
</div>
|
|
|
+
|
|
|
+ {/* Test Panel */}
|
|
|
+ {testModelId && (
|
|
|
+ <div style={{ marginTop: 24, background: '#fff', borderRadius: 8, padding: 20, boxShadow: '0 1px 3px rgba(0,0,0,0.1)' }}>
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
|
|
|
+ <h2 style={{ margin: 0, fontSize: 16 }}>模型测试 — {testModelId}</h2>
|
|
|
+ <button onClick={() => { setTestModelId(''); setTestResult(''); setTestError(''); setTestPrompt('') }} style={{ padding: '4px 12px', borderRadius: 4, border: '1px solid #ccc', background: '#fff', cursor: 'pointer' }}>关闭</button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* Chat-like input */}
|
|
|
+ <div style={{ display: 'flex', gap: 8 }}>
|
|
|
+ <input
|
|
|
+ value={testPrompt}
|
|
|
+ onChange={e => setTestPrompt(e.target.value)}
|
|
|
+ onKeyDown={e => { if (e.key === 'Enter') handleTestSubmit() }}
|
|
|
+ placeholder="输入提示词,按 Enter 发送..."
|
|
|
+ style={{ flex: 1, padding: '10px 12px', borderRadius: 4, border: '1px solid #ccc', fontSize: 14 }}
|
|
|
+ />
|
|
|
+ <button
|
|
|
+ onClick={handleTestSubmit}
|
|
|
+ disabled={testing}
|
|
|
+ style={{ padding: '10px 20px', borderRadius: 4, border: 'none', background: '#2196f3', color: '#fff', cursor: 'pointer', opacity: testing ? 0.6 : 1, whiteSpace: 'nowrap' }}
|
|
|
+ >
|
|
|
+ {testing ? '生成中...' : '发送'}
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* Error */}
|
|
|
+ {testError && (
|
|
|
+ <div style={{ marginTop: 12, padding: 12, background: '#ffebee', borderRadius: 4, color: '#c62828', fontSize: 13 }}>
|
|
|
+ ❌ {testError}
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* Result */}
|
|
|
+ {testResult && (
|
|
|
+ <div style={{ marginTop: 12 }}>
|
|
|
+ <div style={{ display: 'flex', gap: 8, marginBottom: 8 }}>
|
|
|
+ <span style={{ fontSize: 12, color: '#999', background: '#f5f5f5', padding: '2px 8px', borderRadius: 4 }}>Prompt</span>
|
|
|
+ </div>
|
|
|
+ <div style={{ padding: 12, background: '#f0f7ff', borderRadius: 4, fontSize: 14, lineHeight: 1.6, marginBottom: 12 }}>
|
|
|
+ {testPrompt}
|
|
|
+ </div>
|
|
|
+ <div style={{ display: 'flex', gap: 8, marginBottom: 8 }}>
|
|
|
+ <span style={{ fontSize: 12, color: '#999', background: '#f5f5f5', padding: '2px 8px', borderRadius: 4 }}>Response</span>
|
|
|
+ </div>
|
|
|
+ <div style={{ padding: 12, background: '#f0fff0', borderRadius: 4, fontSize: 14, lineHeight: 1.6, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>
|
|
|
+ {testResult}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
</div>
|
|
|
)
|
|
|
}
|