Add embedding preview

This commit is contained in:
Xin Wang
2026-02-10 10:18:19 +08:00
parent 436fb3c1e5
commit 1462488969
3 changed files with 105 additions and 22 deletions

View File

@@ -144,7 +144,13 @@ export const LLMLibraryPage: React.FC = () => {
<TableCell className="font-mono text-xs text-muted-foreground max-w-[240px] truncate">{model.baseUrl}</TableCell>
<TableCell className="font-mono text-xs text-muted-foreground">{maskApiKey(model.apiKey)}</TableCell>
<TableCell className="text-right">
<Button variant="ghost" size="icon" onClick={() => setPreviewingModel(model)} disabled={model.type !== 'text'} title={model.type !== 'text' ? '仅 text 模型可预览' : '预览模型'}>
<Button
variant="ghost"
size="icon"
onClick={() => setPreviewingModel(model)}
disabled={model.type === 'rerank'}
title={model.type === 'rerank' ? '暂不支持 rerank 预览' : (model.type === 'embedding' ? '预览 embedding 向量' : '预览模型')}
>
<Play className="h-4 w-4" />
</Button>
<Button variant="ghost" size="icon" onClick={() => setEditingModel(model)}>
@@ -358,6 +364,7 @@ const LLMPreviewModal: React.FC<{
onClose: () => void;
model: LLMModel | null;
}> = ({ isOpen, onClose, model }) => {
const isEmbeddingModel = model?.type === 'embedding';
const [systemPrompt, setSystemPrompt] = useState('You are a concise helpful assistant.');
const [message, setMessage] = useState('Hello, please introduce yourself in one sentence.');
const [temperature, setTemperature] = useState(0.7);
@@ -419,28 +426,29 @@ const LLMPreviewModal: React.FC<{
value={systemPrompt}
onChange={(e) => setSystemPrompt(e.target.value)}
className="flex min-h-[70px] w-full rounded-md border-0 bg-white/5 px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/50 text-white"
placeholder="可选系统提示词"
placeholder={isEmbeddingModel ? 'embedding 预览无需 system prompt可留空' : '可选系统提示词'}
disabled={isEmbeddingModel}
/>
</div>
<div className="space-y-1.5">
<label className="text-[10px] font-black text-muted-foreground uppercase tracking-widest block">User Message</label>
<label className="text-[10px] font-black text-muted-foreground uppercase tracking-widest block">{isEmbeddingModel ? 'Input Text' : 'User Message'}</label>
<textarea
value={message}
onChange={(e) => setMessage(e.target.value)}
className="flex min-h-[90px] w-full rounded-md border-0 bg-white/5 px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/50 text-white"
placeholder="输入用户消息"
placeholder={isEmbeddingModel ? '输入需要生成向量的文本' : '输入用户消息'}
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-1.5">
<label className="text-[10px] font-black text-muted-foreground uppercase tracking-widest block">Temperature</label>
<Input type="number" min={0} max={2} step={0.1} value={temperature} onChange={(e) => setTemperature(parseFloat(e.target.value || '0'))} />
<Input type="number" min={0} max={2} step={0.1} value={temperature} onChange={(e) => setTemperature(parseFloat(e.target.value || '0'))} disabled={isEmbeddingModel} />
</div>
<div className="space-y-1.5">
<label className="text-[10px] font-black text-muted-foreground uppercase tracking-widest block">Max Tokens</label>
<Input type="number" min={1} value={maxTokens} onChange={(e) => setMaxTokens(parseInt(e.target.value || '1', 10))} />
<Input type="number" min={1} value={maxTokens} onChange={(e) => setMaxTokens(parseInt(e.target.value || '1', 10))} disabled={isEmbeddingModel} />
</div>
</div>