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 };