|
@@ -1,5 +1,6 @@
|
|
|
import { useState, memo } from 'react'
|
|
import { useState, memo } from 'react'
|
|
|
import api, { ModelInfo } from '../api/client'
|
|
import api, { ModelInfo } from '../api/client'
|
|
|
|
|
+import { Cpu, CheckCircle, XCircle } from 'lucide-react'
|
|
|
|
|
|
|
|
const ModelRow = memo(function ModelRow({ m, onTest, onDelete }: {
|
|
const ModelRow = memo(function ModelRow({ m, onTest, onDelete }: {
|
|
|
m: ModelInfo
|
|
m: ModelInfo
|
|
@@ -8,44 +9,44 @@ const ModelRow = memo(function ModelRow({ m, onTest, onDelete }: {
|
|
|
}) {
|
|
}) {
|
|
|
return (
|
|
return (
|
|
|
<tr style={{
|
|
<tr style={{
|
|
|
- borderBottom: '1px solid #f0f0f0',
|
|
|
|
|
|
|
+ borderBottom: '1px solid #f1f5f9',
|
|
|
transition: 'background 0.15s ease',
|
|
transition: 'background 0.15s ease',
|
|
|
}}
|
|
}}
|
|
|
- onMouseEnter={e => { e.currentTarget.style.background = '#fafbfc' }}
|
|
|
|
|
|
|
+ onMouseEnter={e => { e.currentTarget.style.background = '#f0fdfa' }}
|
|
|
onMouseLeave={e => { e.currentTarget.style.background = 'transparent' }}
|
|
onMouseLeave={e => { e.currentTarget.style.background = 'transparent' }}
|
|
|
>
|
|
>
|
|
|
- <td style={{ padding: '12px 12px', fontFamily: 'monospace', fontSize: 12, color: '#666' }}>{m.id}</td>
|
|
|
|
|
|
|
+ <td style={{ padding: '12px 12px', fontFamily: 'monospace', fontSize: 12, color: '#64748b' }}>{m.id}</td>
|
|
|
<td style={{ padding: '12px 12px', fontWeight: 500, fontSize: 13 }}>{m.name}</td>
|
|
<td style={{ padding: '12px 12px', fontWeight: 500, fontSize: 13 }}>{m.name}</td>
|
|
|
- <td style={{ padding: '12px 12px', fontSize: 13, color: '#666' }}>{m.model_type}</td>
|
|
|
|
|
|
|
+ <td style={{ padding: '12px 12px', fontSize: 13, color: '#64748b' }}>{m.model_type}</td>
|
|
|
<td style={{ padding: '12px 12px' }}>
|
|
<td style={{ padding: '12px 12px' }}>
|
|
|
<span style={{
|
|
<span style={{
|
|
|
display: 'inline-block', padding: '3px 10px', borderRadius: 12, fontSize: 12, fontWeight: 500,
|
|
display: 'inline-block', padding: '3px 10px', borderRadius: 12, fontSize: 12, fontWeight: 500,
|
|
|
- background: m.is_downloaded ? '#f0fff4' : '#fff5f7',
|
|
|
|
|
- color: m.is_downloaded ? '#22863a' : '#e94560',
|
|
|
|
|
- border: `1px solid ${m.is_downloaded ? '#d1f0d8' : '#ffdce0'}`,
|
|
|
|
|
|
|
+ background: m.is_downloaded ? '#ecfdf5' : '#fff1f2',
|
|
|
|
|
+ color: m.is_downloaded ? '#059669' : '#f43f5e',
|
|
|
|
|
+ border: `1px solid ${m.is_downloaded ? '#d1fae5' : '#fecdd3'}`,
|
|
|
}}>
|
|
}}>
|
|
|
{m.is_downloaded ? '已缓存' : '未下载'}
|
|
{m.is_downloaded ? '已缓存' : '未下载'}
|
|
|
</span>
|
|
</span>
|
|
|
</td>
|
|
</td>
|
|
|
- <td style={{ padding: '12px 12px', fontSize: 13, color: '#666' }}>{m.supported_peft_methods.join(', ') || '-'}</td>
|
|
|
|
|
|
|
+ <td style={{ padding: '12px 12px', fontSize: 13, color: '#64748b' }}>{m.supported_peft_methods.join(', ') || '-'}</td>
|
|
|
<td style={{ padding: '12px 12px' }}>
|
|
<td style={{ padding: '12px 12px' }}>
|
|
|
{m.is_downloaded && (
|
|
{m.is_downloaded && (
|
|
|
<button onClick={() => onTest(m.id)} style={{
|
|
<button onClick={() => onTest(m.id)} style={{
|
|
|
- marginRight: 8, padding: '4px 12px', color: '#2196f3',
|
|
|
|
|
- border: '1px solid #2196f3', borderRadius: 6, background: 'transparent',
|
|
|
|
|
|
|
+ marginRight: 8, padding: '4px 12px', color: '#0ea5e9',
|
|
|
|
|
+ border: '1px solid #0ea5e9', borderRadius: 6, background: 'transparent',
|
|
|
cursor: 'pointer', fontSize: 12, fontWeight: 500, transition: 'all 0.15s ease',
|
|
cursor: 'pointer', fontSize: 12, fontWeight: 500, transition: 'all 0.15s ease',
|
|
|
}}
|
|
}}
|
|
|
- onMouseEnter={e => { e.currentTarget.style.background = '#2196f3'; e.currentTarget.style.color = '#fff' }}
|
|
|
|
|
- onMouseLeave={e => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = '#2196f3' }}
|
|
|
|
|
|
|
+ onMouseEnter={e => { e.currentTarget.style.background = '#0ea5e9'; e.currentTarget.style.color = '#fff' }}
|
|
|
|
|
+ onMouseLeave={e => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = '#0ea5e9' }}
|
|
|
>测试</button>
|
|
>测试</button>
|
|
|
)}
|
|
)}
|
|
|
<button onClick={() => onDelete(m.id, m.name)} style={{
|
|
<button onClick={() => onDelete(m.id, m.name)} style={{
|
|
|
- padding: '4px 12px', color: '#e94560', border: '1px solid #e94560',
|
|
|
|
|
|
|
+ padding: '4px 12px', color: '#f43f5e', border: '1px solid #f43f5e',
|
|
|
borderRadius: 6, background: 'transparent', cursor: 'pointer',
|
|
borderRadius: 6, background: 'transparent', cursor: 'pointer',
|
|
|
fontSize: 12, fontWeight: 500, transition: 'all 0.15s ease',
|
|
fontSize: 12, fontWeight: 500, transition: 'all 0.15s ease',
|
|
|
}}
|
|
}}
|
|
|
- onMouseEnter={e => { e.currentTarget.style.background = '#e94560'; e.currentTarget.style.color = '#fff' }}
|
|
|
|
|
- onMouseLeave={e => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = '#e94560' }}
|
|
|
|
|
|
|
+ onMouseEnter={e => { e.currentTarget.style.background = '#f43f5e'; e.currentTarget.style.color = '#fff' }}
|
|
|
|
|
+ onMouseLeave={e => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = '#f43f5e' }}
|
|
|
>删除</button>
|
|
>删除</button>
|
|
|
</td>
|
|
</td>
|
|
|
</tr>
|
|
</tr>
|
|
@@ -58,7 +59,8 @@ export function Models() {
|
|
|
const [downloading, setDownloading] = useState(false)
|
|
const [downloading, setDownloading] = useState(false)
|
|
|
const [models, setModels] = useState<ModelInfo[]>([])
|
|
const [models, setModels] = useState<ModelInfo[]>([])
|
|
|
const [loading, setLoading] = useState(false)
|
|
const [loading, setLoading] = useState(false)
|
|
|
- const [statusMsg, setStatusMsg] = useState('')
|
|
|
|
|
|
|
+ const [statusType, setStatusType] = useState<'success' | 'error' | ''>('')
|
|
|
|
|
+ const [statusContent, setStatusContent] = useState('')
|
|
|
|
|
|
|
|
// Test state
|
|
// Test state
|
|
|
const [testModelId, setTestModelId] = useState('')
|
|
const [testModelId, setTestModelId] = useState('')
|
|
@@ -78,10 +80,11 @@ export function Models() {
|
|
|
const handleDownload = () => {
|
|
const handleDownload = () => {
|
|
|
if (!modelId.trim()) return
|
|
if (!modelId.trim()) return
|
|
|
setDownloading(true)
|
|
setDownloading(true)
|
|
|
- setStatusMsg('正在下载...')
|
|
|
|
|
|
|
+ setStatusType('')
|
|
|
|
|
+ setStatusContent('正在下载...')
|
|
|
api.models.download(modelId, useModelscope)
|
|
api.models.download(modelId, useModelscope)
|
|
|
- .then(res => setStatusMsg(`✅ ${res.model_id}: ${res.status}`))
|
|
|
|
|
- .catch(err => setStatusMsg(`❌ 下载失败: ${err.message}`))
|
|
|
|
|
|
|
+ .then(res => { setStatusType('success'); setStatusContent(`${res.model_id}: ${res.status}`) })
|
|
|
|
|
+ .catch(err => { setStatusType('error'); setStatusContent(`下载失败: ${err.message}`) })
|
|
|
.finally(() => setDownloading(false))
|
|
.finally(() => setDownloading(false))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -92,7 +95,8 @@ export function Models() {
|
|
|
fetchModels()
|
|
fetchModels()
|
|
|
} catch (err) {
|
|
} catch (err) {
|
|
|
const msg = err instanceof Error ? err.message : '删除失败'
|
|
const msg = err instanceof Error ? err.message : '删除失败'
|
|
|
- setStatusMsg(`❌ ${msg}`)
|
|
|
|
|
|
|
+ setStatusType('error')
|
|
|
|
|
+ setStatusContent(msg)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -101,7 +105,6 @@ export function Models() {
|
|
|
setTestPrompt('')
|
|
setTestPrompt('')
|
|
|
setTestResult('')
|
|
setTestResult('')
|
|
|
setTestError('')
|
|
setTestError('')
|
|
|
- // Show test panel
|
|
|
|
|
setTestPrompt('你好,请简单介绍一下自己。')
|
|
setTestPrompt('你好,请简单介绍一下自己。')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -130,7 +133,7 @@ export function Models() {
|
|
|
return (
|
|
return (
|
|
|
<div>
|
|
<div>
|
|
|
<h1 style={{ margin: 0, fontSize: 22, fontWeight: 700 }}>模型注册</h1>
|
|
<h1 style={{ margin: 0, fontSize: 22, fontWeight: 700 }}>模型注册</h1>
|
|
|
- <p style={{ color: '#888', fontSize: 13, margin: '4px 0 16px' }}>下载和管理预训练模型</p>
|
|
|
|
|
|
|
+ <p style={{ color: '#64748b', fontSize: 13, margin: '4px 0 16px' }}>下载和管理预训练模型</p>
|
|
|
|
|
|
|
|
{/* Download form */}
|
|
{/* Download form */}
|
|
|
<div style={{
|
|
<div style={{
|
|
@@ -146,13 +149,13 @@ export function Models() {
|
|
|
onChange={e => setModelId(e.target.value)}
|
|
onChange={e => setModelId(e.target.value)}
|
|
|
style={{
|
|
style={{
|
|
|
padding: '10px 14px', flex: 1, maxWidth: 400, borderRadius: 8,
|
|
padding: '10px 14px', flex: 1, maxWidth: 400, borderRadius: 8,
|
|
|
- border: '1px solid #d0d0d0', fontSize: 14, outline: 'none',
|
|
|
|
|
|
|
+ border: '1px solid #cbd5e1', fontSize: 14, outline: 'none',
|
|
|
transition: 'border-color 0.2s',
|
|
transition: 'border-color 0.2s',
|
|
|
}}
|
|
}}
|
|
|
- onFocus={e => { e.currentTarget.style.borderColor = '#e94560' }}
|
|
|
|
|
- onBlur={e => { e.currentTarget.style.borderColor = '#d0d0d0' }}
|
|
|
|
|
|
|
+ onFocus={e => { e.currentTarget.style.borderColor = '#14b8a6' }}
|
|
|
|
|
+ onBlur={e => { e.currentTarget.style.borderColor = '#cbd5e1' }}
|
|
|
/>
|
|
/>
|
|
|
- <label style={{ fontSize: 13, color: '#666', whiteSpace: 'nowrap', display: 'flex', alignItems: 'center', gap: 4, cursor: 'pointer' }}>
|
|
|
|
|
|
|
+ <label style={{ fontSize: 13, color: '#64748b', whiteSpace: 'nowrap', display: 'flex', alignItems: 'center', gap: 4, cursor: 'pointer' }}>
|
|
|
<input type="checkbox" checked={useModelscope} onChange={e => setUseModelscope(e.target.checked)} />
|
|
<input type="checkbox" checked={useModelscope} onChange={e => setUseModelscope(e.target.checked)} />
|
|
|
{' '}ModelScope
|
|
{' '}ModelScope
|
|
|
</label>
|
|
</label>
|
|
@@ -161,7 +164,7 @@ export function Models() {
|
|
|
disabled={downloading}
|
|
disabled={downloading}
|
|
|
style={{
|
|
style={{
|
|
|
padding: '10px 20px', borderRadius: 8, border: 'none',
|
|
padding: '10px 20px', borderRadius: 8, border: 'none',
|
|
|
- background: '#e94560', color: '#fff', cursor: 'pointer',
|
|
|
|
|
|
|
+ background: '#14b8a6', color: '#fff', cursor: 'pointer',
|
|
|
opacity: downloading ? 0.6 : 1, fontSize: 14, fontWeight: 600,
|
|
opacity: downloading ? 0.6 : 1, fontSize: 14, fontWeight: 600,
|
|
|
transition: 'all 0.2s ease',
|
|
transition: 'all 0.2s ease',
|
|
|
}}
|
|
}}
|
|
@@ -169,14 +172,16 @@ export function Models() {
|
|
|
{downloading ? '下载中...' : '下载模型'}
|
|
{downloading ? '下载中...' : '下载模型'}
|
|
|
</button>
|
|
</button>
|
|
|
</div>
|
|
</div>
|
|
|
- {statusMsg && (
|
|
|
|
|
|
|
+ {statusType && (
|
|
|
<p style={{
|
|
<p style={{
|
|
|
marginTop: 10, padding: '8px 12px', borderRadius: 6, fontSize: 13, margin: '10px 0 0',
|
|
marginTop: 10, padding: '8px 12px', borderRadius: 6, fontSize: 13, margin: '10px 0 0',
|
|
|
- background: statusMsg.includes('❌') ? '#fff2f0' : '#f0fff4',
|
|
|
|
|
- color: statusMsg.includes('❌') ? '#cf1322' : '#22863a',
|
|
|
|
|
- border: `1px solid ${statusMsg.includes('❌') ? '#ffccc7' : '#d1f0d8'}`,
|
|
|
|
|
|
|
+ display: 'flex', alignItems: 'center', gap: 6,
|
|
|
|
|
+ background: statusType === 'error' ? '#fff1f2' : '#ecfdf5',
|
|
|
|
|
+ color: statusType === 'error' ? '#e11d48' : '#059669',
|
|
|
|
|
+ border: `1px solid ${statusType === 'error' ? '#fecdd3' : '#d1fae5'}`,
|
|
|
}}>
|
|
}}>
|
|
|
- {statusMsg}
|
|
|
|
|
|
|
+ {statusType === 'error' ? <XCircle size={14} /> : <CheckCircle size={14} />}
|
|
|
|
|
+ {statusContent}
|
|
|
</p>
|
|
</p>
|
|
|
)}
|
|
)}
|
|
|
</div>
|
|
</div>
|
|
@@ -186,25 +191,25 @@ export function Models() {
|
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
|
|
|
<h2 style={{ margin: 0, fontSize: 15, fontWeight: 600 }}>已缓存模型</h2>
|
|
<h2 style={{ margin: 0, fontSize: 15, fontWeight: 600 }}>已缓存模型</h2>
|
|
|
<button onClick={fetchModels} style={{
|
|
<button onClick={fetchModels} style={{
|
|
|
- padding: '6px 14px', borderRadius: 6, border: '1px solid #d0d0d0',
|
|
|
|
|
|
|
+ padding: '6px 14px', borderRadius: 6, border: '1px solid #cbd5e1',
|
|
|
background: '#fff', cursor: 'pointer', fontSize: 13, fontWeight: 500,
|
|
background: '#fff', cursor: 'pointer', fontSize: 13, fontWeight: 500,
|
|
|
transition: 'all 0.15s ease',
|
|
transition: 'all 0.15s ease',
|
|
|
}}
|
|
}}
|
|
|
- onMouseEnter={e => { e.currentTarget.style.background = '#f5f5f5' }}
|
|
|
|
|
|
|
+ onMouseEnter={e => { e.currentTarget.style.background = '#f0fdfa' }}
|
|
|
onMouseLeave={e => { e.currentTarget.style.background = '#fff' }}
|
|
onMouseLeave={e => { e.currentTarget.style.background = '#fff' }}
|
|
|
>
|
|
>
|
|
|
刷新
|
|
刷新
|
|
|
</button>
|
|
</button>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- {loading && <p style={{ color: '#999', fontSize: 13 }}>加载中...</p>}
|
|
|
|
|
|
|
+ {loading && <p style={{ color: '#94a3b8', fontSize: 13 }}>加载中...</p>}
|
|
|
|
|
|
|
|
{!loading && models.length === 0 && (
|
|
{!loading && models.length === 0 && (
|
|
|
<div style={{
|
|
<div style={{
|
|
|
- padding: 40, textAlign: 'center', color: '#999', fontSize: 14,
|
|
|
|
|
|
|
+ padding: 40, textAlign: 'center', color: '#94a3b8', fontSize: 14,
|
|
|
background: '#fff', borderRadius: 10, boxShadow: '0 1px 3px rgba(0,0,0,0.06)',
|
|
background: '#fff', borderRadius: 10, boxShadow: '0 1px 3px rgba(0,0,0,0.06)',
|
|
|
}}>
|
|
}}>
|
|
|
- <div style={{ fontSize: 32, marginBottom: 8 }}>🧠</div>
|
|
|
|
|
|
|
+ <div style={{ marginBottom: 8 }}><Cpu size={32} color="#94a3b8" strokeWidth={1.5} /></div>
|
|
|
暂无已缓存模型,请在上方下载模型
|
|
暂无已缓存模型,请在上方下载模型
|
|
|
</div>
|
|
</div>
|
|
|
)}
|
|
)}
|
|
@@ -216,13 +221,13 @@ export function Models() {
|
|
|
}}>
|
|
}}>
|
|
|
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 14 }}>
|
|
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 14 }}>
|
|
|
<thead>
|
|
<thead>
|
|
|
- <tr style={{ background: '#fafbfc', borderBottom: '2px solid #f0f0f0', textAlign: 'left' }}>
|
|
|
|
|
- <th style={{ padding: '10px 12px', fontSize: 12, color: '#666', fontWeight: 600 }}>ID</th>
|
|
|
|
|
- <th style={{ padding: '10px 12px', fontSize: 12, color: '#666', fontWeight: 600 }}>名称</th>
|
|
|
|
|
- <th style={{ padding: '10px 12px', fontSize: 12, color: '#666', fontWeight: 600 }}>类型</th>
|
|
|
|
|
- <th style={{ padding: '10px 12px', fontSize: 12, color: '#666', fontWeight: 600 }}>状态</th>
|
|
|
|
|
- <th style={{ padding: '10px 12px', fontSize: 12, color: '#666', fontWeight: 600 }}>PEFT 支持</th>
|
|
|
|
|
- <th style={{ padding: '10px 12px', fontSize: 12, color: '#666', fontWeight: 600 }}>操作</th>
|
|
|
|
|
|
|
+ <tr style={{ background: '#f0fdfa', borderBottom: '2px solid #f1f5f9', textAlign: 'left' }}>
|
|
|
|
|
+ <th style={{ padding: '10px 12px', fontSize: 12, color: '#64748b', fontWeight: 600 }}>ID</th>
|
|
|
|
|
+ <th style={{ padding: '10px 12px', fontSize: 12, color: '#64748b', fontWeight: 600 }}>名称</th>
|
|
|
|
|
+ <th style={{ padding: '10px 12px', fontSize: 12, color: '#64748b', fontWeight: 600 }}>类型</th>
|
|
|
|
|
+ <th style={{ padding: '10px 12px', fontSize: 12, color: '#64748b', fontWeight: 600 }}>状态</th>
|
|
|
|
|
+ <th style={{ padding: '10px 12px', fontSize: 12, color: '#64748b', fontWeight: 600 }}>PEFT 支持</th>
|
|
|
|
|
+ <th style={{ padding: '10px 12px', fontSize: 12, color: '#64748b', fontWeight: 600 }}>操作</th>
|
|
|
</tr>
|
|
</tr>
|
|
|
</thead>
|
|
</thead>
|
|
|
<tbody>
|
|
<tbody>
|
|
@@ -242,9 +247,9 @@ export function Models() {
|
|
|
boxShadow: '0 2px 8px rgba(0,0,0,0.08)', border: '1px solid rgba(0,0,0,0.04)',
|
|
boxShadow: '0 2px 8px rgba(0,0,0,0.08)', border: '1px solid rgba(0,0,0,0.04)',
|
|
|
}}>
|
|
}}>
|
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
|
|
|
- <h2 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>模型测试 — <code style={{ background: '#f5f5f5', padding: '2px 8px', borderRadius: 4, fontSize: 13 }}>{testModelId}</code></h2>
|
|
|
|
|
|
|
+ <h2 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>模型测试 — <code style={{ background: '#f1f5f9', padding: '2px 8px', borderRadius: 4, fontSize: 13 }}>{testModelId}</code></h2>
|
|
|
<button onClick={() => { setTestModelId(''); setTestResult(''); setTestError(''); setTestPrompt('') }} style={{
|
|
<button onClick={() => { setTestModelId(''); setTestResult(''); setTestError(''); setTestPrompt('') }} style={{
|
|
|
- padding: '6px 14px', borderRadius: 6, border: '1px solid #d0d0d0',
|
|
|
|
|
|
|
+ padding: '6px 14px', borderRadius: 6, border: '1px solid #cbd5e1',
|
|
|
background: '#fff', cursor: 'pointer', fontSize: 13,
|
|
background: '#fff', cursor: 'pointer', fontSize: 13,
|
|
|
}}>关闭</button>
|
|
}}>关闭</button>
|
|
|
</div>
|
|
</div>
|
|
@@ -258,18 +263,18 @@ export function Models() {
|
|
|
placeholder="输入提示词,按 Enter 发送..."
|
|
placeholder="输入提示词,按 Enter 发送..."
|
|
|
style={{
|
|
style={{
|
|
|
flex: 1, padding: '10px 14px', borderRadius: 8,
|
|
flex: 1, padding: '10px 14px', borderRadius: 8,
|
|
|
- border: '1px solid #d0d0d0', fontSize: 14, outline: 'none',
|
|
|
|
|
|
|
+ border: '1px solid #cbd5e1', fontSize: 14, outline: 'none',
|
|
|
transition: 'border-color 0.2s',
|
|
transition: 'border-color 0.2s',
|
|
|
}}
|
|
}}
|
|
|
- onFocus={e => { e.currentTarget.style.borderColor = '#2196f3' }}
|
|
|
|
|
- onBlur={e => { e.currentTarget.style.borderColor = '#d0d0d0' }}
|
|
|
|
|
|
|
+ onFocus={e => { e.currentTarget.style.borderColor = '#0ea5e9' }}
|
|
|
|
|
+ onBlur={e => { e.currentTarget.style.borderColor = '#cbd5e1' }}
|
|
|
/>
|
|
/>
|
|
|
<button
|
|
<button
|
|
|
onClick={handleTestSubmit}
|
|
onClick={handleTestSubmit}
|
|
|
disabled={testing}
|
|
disabled={testing}
|
|
|
style={{
|
|
style={{
|
|
|
padding: '10px 24px', borderRadius: 8, border: 'none',
|
|
padding: '10px 24px', borderRadius: 8, border: 'none',
|
|
|
- background: '#2196f3', color: '#fff', cursor: 'pointer',
|
|
|
|
|
|
|
+ background: '#0ea5e9', color: '#fff', cursor: 'pointer',
|
|
|
opacity: testing ? 0.6 : 1, whiteSpace: 'nowrap', fontSize: 14, fontWeight: 600,
|
|
opacity: testing ? 0.6 : 1, whiteSpace: 'nowrap', fontSize: 14, fontWeight: 600,
|
|
|
transition: 'all 0.2s ease',
|
|
transition: 'all 0.2s ease',
|
|
|
}}
|
|
}}
|
|
@@ -280,7 +285,7 @@ export function Models() {
|
|
|
|
|
|
|
|
{/* Error */}
|
|
{/* Error */}
|
|
|
{testError && (
|
|
{testError && (
|
|
|
- <div style={{ marginTop: 16, padding: 12, background: '#fff2f0', borderRadius: 8, color: '#cf1322', fontSize: 13, border: '1px solid #ffccc7' }}>
|
|
|
|
|
|
|
+ <div style={{ marginTop: 16, padding: 12, background: '#fff1f2', borderRadius: 8, color: '#e11d48', fontSize: 13, border: '1px solid #fecdd3' }}>
|
|
|
{testError}
|
|
{testError}
|
|
|
</div>
|
|
</div>
|
|
|
)}
|
|
)}
|
|
@@ -289,15 +294,15 @@ export function Models() {
|
|
|
{testResult && (
|
|
{testResult && (
|
|
|
<div style={{ marginTop: 16 }}>
|
|
<div style={{ marginTop: 16 }}>
|
|
|
<div style={{ display: 'flex', gap: 8, marginBottom: 8 }}>
|
|
<div style={{ display: 'flex', gap: 8, marginBottom: 8 }}>
|
|
|
- <span style={{ fontSize: 12, color: '#666', fontWeight: 600 }}>Prompt</span>
|
|
|
|
|
|
|
+ <span style={{ fontSize: 12, color: '#64748b', fontWeight: 600 }}>Prompt</span>
|
|
|
</div>
|
|
</div>
|
|
|
- <div style={{ padding: 14, background: '#f0f7ff', borderRadius: 8, fontSize: 14, lineHeight: 1.6, marginBottom: 16, border: '1px solid #d6e8fa' }}>
|
|
|
|
|
|
|
+ <div style={{ padding: 14, background: '#f0f9ff', borderRadius: 8, fontSize: 14, lineHeight: 1.6, marginBottom: 16, border: '1px solid #bae6fd' }}>
|
|
|
{testPrompt}
|
|
{testPrompt}
|
|
|
</div>
|
|
</div>
|
|
|
<div style={{ display: 'flex', gap: 8, marginBottom: 8 }}>
|
|
<div style={{ display: 'flex', gap: 8, marginBottom: 8 }}>
|
|
|
- <span style={{ fontSize: 12, color: '#666', fontWeight: 600 }}>Response</span>
|
|
|
|
|
|
|
+ <span style={{ fontSize: 12, color: '#64748b', fontWeight: 600 }}>Response</span>
|
|
|
</div>
|
|
</div>
|
|
|
- <div style={{ padding: 14, background: '#f0fff4', borderRadius: 8, fontSize: 14, lineHeight: 1.6, whiteSpace: 'pre-wrap', wordBreak: 'break-word', border: '1px solid #d1f0d8' }}>
|
|
|
|
|
|
|
+ <div style={{ padding: 14, background: '#ecfdf5', borderRadius: 8, fontSize: 14, lineHeight: 1.6, whiteSpace: 'pre-wrap', wordBreak: 'break-word', border: '1px solid #d1fae5' }}>
|
|
|
{testResult}
|
|
{testResult}
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|