File size: 3,544 Bytes
4602745 674994f 4602745 674994f d4f1e7c 674994f d4f1e7c 4602745 674994f 4602745 674994f 4602745 674994f 4602745 674994f 4602745 674994f 4602745 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | /**
* ModelSelector.jsx
* Dropdown for choosing the ASR model.
* WebGPU models (mode: 'webgpu') are tagged "Client-Side (WebGPU)";
* others are tagged by their server-side engine.
*/
const MODELS = [
{ value: 'whisper-base-hf-gpu', id: 'openai/whisper-base', label: 'Whisper Base (Server: HF-GPU Fast)', mode: 'server', engine: 'hf-gpu' },
{ value: 'whisper-base-hf-cpu', id: 'openai/whisper-base', label: 'Whisper Base (Server: HF-CPU Safe)', mode: 'server', engine: 'hf-cpu' },
{ value: 'cohere-hf-gpu', id: 'CohereLabs/cohere-transcribe-03-2026', label: 'cohere-transcribe-03-2026 (HF-GPU Safe)', mode: 'server', engine: 'hf-gpu' },
{ value: 'cohere-hf-cpu', id: 'CohereLabs/cohere-transcribe-03-2026', label: 'cohere-transcribe-03-2026 (HF-CPU Safe)', mode: 'server', engine: 'hf-cpu' },
{ value: 'qwen3-asr-hf-gpu', id: 'Qwen3-ASR-1.7B', label: 'Qwen3-ASR 1.7B (HF-GPU)', mode: 'server', engine: 'hf-gpu' },
{ value: 'granite-hf-gpu', id: 'ibm-granite/granite-4.0-1b-speech', label: 'Granite 4.0 1B Speech (HF-GPU)', mode: 'server', engine: 'hf-gpu' },
{ value: 'granite-vllm', id: 'ibm-granite/granite-4.0-1b-speech', label: 'Granite 4.0 1B Speech (vLLM Cloud)', mode: 'server', engine: 'vllm' },
{ value: 'whisper-tiny-webgpu', id: 'Xenova/whisper-tiny', label: 'Whisper Tiny (WebGPU Safe)', mode: 'webgpu' },
{ value: 'whisper-base-webgpu', id: 'Xenova/whisper-base', label: 'Whisper Base (WebGPU - Unstable)', mode: 'webgpu' },
{ value: 'cohere-webgpu', id: 'onnx-community/cohere-transcribe-03-2026-ONNX', label: 'cohere-transcribe-03-2026 (WebGPU)', mode: 'webgpu' },
];
const BADGE = {
'vllm-server': { label: 'vLLM 路 Server-Side', color: '#4f46e5' },
'hf-gpu-server': { label: 'HF GPU 路 Server-Side', color: '#2563eb' },
'hf-cpu-server': { label: 'HF CPU 路 Server-Side', color: '#0f766e' },
webgpu: { label: 'WebGPU 路 Client-Side', color: '#059669' },
};
function modelBadge(model) {
if (model.mode === 'webgpu') return BADGE.webgpu;
if (model.engine === 'hf-gpu') return BADGE['hf-gpu-server'];
if (model.engine === 'hf-cpu') return BADGE['hf-cpu-server'];
return BADGE['vllm-server'];
}
function modelTitle(model) {
if (model.mode === 'webgpu') {
return 'Runs entirely in the browser - no audio leaves your device';
}
if (model.engine === 'hf-gpu') {
return 'Routes audio to backend transformers on GPU';
}
if (model.engine === 'hf-cpu') {
return 'Routes audio to backend transformers on CPU';
}
return 'Routes audio to FastAPI/vLLM backend';
}
export function getModelByValue(value) {
return MODELS.find((m) => m.value === value) ?? MODELS[0];
}
export default function ModelSelector({ value, onChange, disabled }) {
const selected = getModelByValue(value);
const badge = modelBadge(selected);
return (
<div className="model-selector">
<label htmlFor="model-select" className="label">
Model
</label>
<div className="select-row">
<select
id="model-select"
value={value}
onChange={(e) => onChange(e.target.value)}
disabled={disabled}
className="select"
>
{MODELS.map((m) => (
<option key={m.value} value={m.value}>
{m.label}
</option>
))}
</select>
<span
className="badge"
style={{ backgroundColor: badge.color }}
title={modelTitle(selected)}
>
{badge.label}
</span>
</div>
</div>
);
}
export { MODELS };
|