HTML 77.2%
TypeScript 10.5%
Python 9.6%
JavaScript 2.5%
1import Link from 'next/link';2import { APPLE_PRESETS, NVIDIA_PRESETS, QUANTS } from '@/components/hardware/fit-form';3import { BTN_GHOST, CTRL, Field } from './bits';45/* GET form for /find-a-model — "What do you need?" Every field maps 1:1 to a `/find-a-model` parameter. */6export const FINDER_USE_CASES = [7 { value: '', label: 'Any' },8 { value: 'chat', label: 'Chat / assistant' },9 { value: 'coding', label: 'Coding' },10 { value: 'reasoning', label: 'Reasoning / math' },11 { value: 'agentic', label: 'Agentic / tool use' },12 { value: 'long_context', label: 'Long context' },13 { value: 'vision', label: 'Vision' },14 { value: 'embeddings', label: 'Embeddings' },15 { value: 'low_cost', label: 'Low cost' },16 { value: 'local', label: 'Runs locally' },17];18export const MODALITIES = ['text', 'image', 'audio', 'video', 'embedding'];19export type FinderInputs = { useCase: string; deployment: 'any' | 'local' | 'api'; memory: number | null; quant: string; contextMin: number | null; license: 'any' | 'commercial'; openness: string; maxIn: number | null; maxOut: number | null; modalities: string[] };2021export function FinderForm({ v, className }: { v: FinderInputs; className?: string }) {22 const presets = [...APPLE_PRESETS, ...NVIDIA_PRESETS];23 const presetSelected = v.memory !== null && presets.includes(v.memory) ? String(v.memory) : '';24 const radio = (name: string, value: string, current: string, label: string) => (25 <label className="inline-flex min-h-11 cursor-pointer items-center lg:min-h-9 gap-1.5 border border-rule px-2.5 text-sm text-ink-2 has-[:checked]:border-ink has-[:checked]:bg-ink has-[:checked]:text-canvas">26 <input type="radio" name={name} value={value} defaultChecked={current === value} className="sr-only" /> {label}27 </label>28 );29 return (30 <form action="/find-a-model" method="get" className={`space-y-3 ${className ?? ''}`} data-finder-form>31 <Field label="Use case">32 <select name="use_case" defaultValue={v.useCase} className={CTRL}>33 {FINDER_USE_CASES.map((u) => (34 <option key={u.value} value={u.value}>35 {u.label}36 </option>37 ))}38 </select>39 </Field>40 <div>41 <span className="eyebrow block pb-1">Deployment</span>42 <div className="flex flex-wrap gap-1.5" role="radiogroup" aria-label="Deployment">43 {radio('deployment', 'any', v.deployment, 'Any')}44 {radio('deployment', 'local', v.deployment, 'Local')}45 {radio('deployment', 'api', v.deployment, 'API')}46 </div>47 </div>48 <Field label="Memory (local)" hint="Used for the estimated fit when deployment is local.">49 <select name="memory_gb" defaultValue={presetSelected} className={CTRL}>50 <option value="">Not specified</option>51 <optgroup label="Apple silicon">52 {APPLE_PRESETS.map((g) => (53 <option key={`a${g}`} value={g}>54 {g} GB55 </option>56 ))}57 </optgroup>58 <optgroup label="NVIDIA">59 {NVIDIA_PRESETS.map((g) => (60 <option key={`n${g}`} value={g}>61 {g} GB62 </option>63 ))}64 </optgroup>65 </select>66 </Field>67 <Field label="…or any memory (GB)">68 <input name="memory_custom" inputMode="decimal" defaultValue={presetSelected ? '' : v.memory ?? ''} placeholder="e.g. 20" className={CTRL} />69 </Field>70 <Field label="Quantization (local)">71 <select name="quant" defaultValue={v.quant} className={CTRL}>72 {QUANTS.map((q) => (73 <option key={q.value} value={q.value}>74 {q.label}75 </option>76 ))}77 </select>78 </Field>79 <Field label="Context ≥ (tokens)">80 <select name="context_min" defaultValue={v.contextMin ? String(v.contextMin) : ''} className={CTRL}>81 <option value="">Any</option>82 <option value="32768">32K</option>83 <option value="128000">128K</option>84 <option value="200000">200K</option>85 <option value="1000000">1M</option>86 </select>87 </Field>88 <div>89 <span className="eyebrow block pb-1">Licence</span>90 <div className="flex flex-wrap gap-1.5" role="radiogroup" aria-label="Licence">91 {radio('license', 'any', v.license, 'Any')}92 {radio('license', 'commercial', v.license, 'Commercial use allowed')}93 </div>94 </div>95 <Field label="Openness">96 <select name="openness" defaultValue={v.openness} className={CTRL}>97 <option value="">Any</option>98 <option value="open-source">Open source</option>99 <option value="open-weights">Open weights</option>100 <option value="restricted-weights">Restricted weights</option>101 <option value="proprietary">Proprietary</option>102 </select>103 </Field>104 <div className="grid grid-cols-2 gap-2">105 <Field label="Max input $/1M">106 <input name="max_input_price" inputMode="decimal" defaultValue={v.maxIn ?? ''} placeholder="e.g. 1" className={CTRL} />107 </Field>108 <Field label="Max output $/1M">109 <input name="max_output_price" inputMode="decimal" defaultValue={v.maxOut ?? ''} placeholder="e.g. 5" className={CTRL} />110 </Field>111 </div>112 <div>113 <span className="eyebrow block pb-1">Modalities (all required)</span>114 <div className="flex flex-wrap gap-1.5">115 {MODALITIES.map((m) => (116 <label key={m} className="inline-flex min-h-11 cursor-pointer items-center lg:min-h-9 gap-1.5 border border-rule px-2.5 text-sm text-ink-2 has-[:checked]:border-ink has-[:checked]:bg-ink has-[:checked]:text-canvas">117 <input type="checkbox" name="mod" value={m} defaultChecked={v.modalities.includes(m)} className="sr-only" /> {m}118 </label>119 ))}120 </div>121 </div>122 <div className="flex gap-2">123 <button type="submit" className="inline-flex h-11 flex-1 items-center justify-center bg-ink lg:h-10 px-3 text-sm font-medium text-canvas hover:opacity-90">124 Find models125 </button>126 <Link href="/find-a-model" className={BTN_GHOST}>127 Reset128 </Link>129 </div>130 </form>131 );132}133