Spaces:
Sleeping
Sleeping
File size: 4,588 Bytes
43d708a 0e54f19 43d708a 8e038ca 43d708a 0e54f19 43d708a 8e038ca 25f6a95 43d708a 8e038ca 43d708a 8e038ca 43d708a 11ba25d 8e038ca 43d708a 8e038ca 43d708a 8e038ca | 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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | "use client"
import { useState, useEffect } from "react"
import { getAvailableModels } from "../lib/api"
interface Model {
id: string
name: string
description?: string
}
export default function ModelSelector({
models,
onAdd,
onRemove,
}: {
models: string[]
onAdd: (id: string) => void
onRemove: (id: string) => void
}) {
const [allModels, setAllModels] = useState<Model[]>([])
const [loading, setLoading] = useState(true)
const full = models.length >= 6
useEffect(() => {
async function fetchModels() {
try {
const data = await getAvailableModels()
// Use unified model list (no backend categorization)
// Support multiple backend response formats (new unified `models` or legacy grouped keys)
if (data.models && Array.isArray(data.models)) {
setAllModels(data.models)
} else {
const groq = data.groq_models || data.groqModels || data.groq || []
const hf = data.hf_spaces_models || data.hf_spaces || data.hf_models || data.hfModels || []
const merged: Model[] = []
if (Array.isArray(groq)) {
for (const g of groq) merged.push({ id: g.id, name: g.name || g.id, description: g.description || g.backend || '' })
}
if (Array.isArray(hf)) {
for (const h of hf) merged.push({ id: h.id, name: h.name || h.id, description: h.description || h.space_url || '' })
}
if (merged.length > 0) setAllModels(merged)
else setAllModels([])
}
} catch (err) {
console.error("Failed to fetch models:", err)
// Fallback to default models
setAllModels([
{ id: "mixtral-8x7b-32768", name: "Mixtral 8x7B", description: "High-performance model" },
{ id: "llama2-70b-4096", name: "Llama 2 70B", description: "Large instruction-tuned model" },
{ id: "mistralai/Mistral-7B-Instruct-v0.2", name: "Mistral 7B", description: "Fast 7B model" },
{ id: "NousResearch/Nous-Hermes-2-Mistral-7B-DPO", name: "Nous Hermes 2", description: "High-quality model" },
])
} finally {
setLoading(false)
}
}
fetchModels()
}, [])
if (loading) {
return (
<div className="px-4 py-6 space-y-6">
<div className="text-center text-white/40 font-mono text-xs">
Loading models...
</div>
</div>
)
}
return (
<div className="px-4 py-6 space-y-6">
<div>
<h3 className="text-[10px] font-mono text-white/30 uppercase tracking-[0.2em] mb-4">
Select Survivors ({models.length}/6)
</h3>
<div className="space-y-1.5 max-h-[400px] overflow-y-auto overflow-x-hidden">
{allModels.map((m) => {
const isSelected = models.includes(m.id)
return (
<button
key={m.id}
onClick={() => isSelected ? onRemove(m.id) : onAdd(m.id)}
disabled={full && !isSelected}
className={`w-full flex items-center justify-between px-3 py-2 rounded-lg border transition-all duration-200 ${
isSelected
? 'bg-white/10 border-white/20'
: 'border-transparent hover:bg-white/5 opacity-60 hover:opacity-100'
} ${full && !isSelected ? 'cursor-not-allowed opacity-20' : ''}`}
title={m.description}
>
<span className="font-mono text-xs text-white/90 text-left flex-1">{m.name}</span>
<span className={`text-[8px] font-mono ml-2 px-2 py-1 rounded ${isSelected ? 'bg-white/20 text-white' : 'text-white/30'}`}>
{isSelected ? "✓" : "○"}
</span>
</button>
)
})}
</div>
</div>
{models.length > 0 && (
<div className="pt-4 border-t border-white/5">
<div className="flex flex-wrap gap-2">
{models.map(id => {
const model = allModels.find(m => m.id === id)
return (
<div key={id} className="flex items-center gap-2 bg-white/5 px-2 py-1 rounded border border-white/10">
<span className="font-mono text-[10px] text-white/50">
{model?.name || id.split("/").pop()}
</span>
<button onClick={() => onRemove(id)} className="text-white/20 hover:text-white">✕</button>
</div>
)
})}
</div>
</div>
)}
</div>
)
}
|