| import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card' | |
| import { Slider } from '@/components/ui/slider' | |
| import { Label } from '@/components/ui/label' | |
| import { Badge } from '@/components/ui/badge' | |
| import { | |
| Select, | |
| SelectContent, | |
| SelectGroup, | |
| SelectItem, | |
| SelectLabel, | |
| SelectTrigger, | |
| SelectValue, | |
| } from '@/components/ui/select' | |
| import { Cloud, Brain, Zap } from 'lucide-react' | |
| interface ModelInfo { | |
| model_name: string | |
| name: string | |
| supports_thinking: boolean | |
| description: string | |
| size_gb: string | |
| is_loaded: boolean | |
| type: 'local' | 'api' | |
| } | |
| interface ModelParametersTabProps { | |
| models: ModelInfo[] | |
| selectedModel: string | null | |
| setSelectedModel: (model: string) => void | |
| autoLoadingModel: string | null | |
| temperature: number | |
| setTemperature: (temp: number) => void | |
| maxTokens: number | |
| setMaxTokens: (tokens: number) => void | |
| } | |
| export function ModelParametersTab({ | |
| models, | |
| selectedModel, | |
| setSelectedModel, | |
| autoLoadingModel, | |
| temperature, | |
| setTemperature, | |
| maxTokens, | |
| setMaxTokens | |
| }: ModelParametersTabProps) { | |
| return ( | |
| <> | |
| {/* Model Selection */} | |
| <Card> | |
| <CardHeader> | |
| <CardTitle className="text-base">Model</CardTitle> | |
| </CardHeader> | |
| <CardContent className="space-y-4"> | |
| <div> | |
| <Select value={selectedModel || ""} onValueChange={setSelectedModel}> | |
| <SelectTrigger className="w-full"> | |
| <SelectValue placeholder="Select a model..."> | |
| {selectedModel && (() => { | |
| const model = models.find(m => m.model_name === selectedModel) | |
| if (!model) return selectedModel | |
| const isApiModel = model.type === 'api' | |
| return ( | |
| <div className="flex items-center gap-2"> | |
| {isApiModel ? ( | |
| <Cloud className="h-4 w-4 text-blue-500" /> | |
| ) : model.supports_thinking ? ( | |
| <Brain className="h-4 w-4 text-purple-500" /> | |
| ) : ( | |
| <Zap className="h-4 w-4 text-green-500" /> | |
| )} | |
| <span className="truncate">{model.name}</span> | |
| {autoLoadingModel === selectedModel ? ( | |
| <Badge variant="outline" className="text-xs"> | |
| Loading... | |
| </Badge> | |
| ) : ( | |
| <Badge variant="outline" className="text-xs"> | |
| {isApiModel ? "API" : model.is_loaded ? "Loaded" : "Available"} | |
| </Badge> | |
| )} | |
| </div> | |
| ) | |
| })()} | |
| </SelectValue> | |
| </SelectTrigger> | |
| <SelectContent> | |
| <SelectGroup> | |
| <SelectLabel>π API Models</SelectLabel> | |
| {models.filter(m => m.type === 'api').map((model) => ( | |
| <SelectItem key={model.model_name} value={model.model_name}> | |
| <div className="flex items-center gap-2"> | |
| <Cloud className="h-4 w-4 text-blue-500" /> | |
| <span>{model.name}</span> | |
| <Badge variant="outline" className="text-xs bg-blue-50">API</Badge> | |
| </div> | |
| </SelectItem> | |
| ))} | |
| </SelectGroup> | |
| <SelectGroup> | |
| <SelectLabel>π» Local Models</SelectLabel> | |
| {models.filter(m => m.type === 'local').map((model) => ( | |
| <SelectItem key={model.model_name} value={model.model_name}> | |
| <div className="flex items-center gap-2"> | |
| {model.supports_thinking ? ( | |
| <Brain className="h-4 w-4 text-purple-500" /> | |
| ) : ( | |
| <Zap className="h-4 w-4 text-green-500" /> | |
| )} | |
| <span>{model.name}</span> | |
| {autoLoadingModel === model.model_name ? ( | |
| <Badge variant="outline" className="text-xs bg-yellow-50">Loading...</Badge> | |
| ) : model.is_loaded ? ( | |
| <Badge variant="outline" className="text-xs bg-green-50">Loaded</Badge> | |
| ) : ( | |
| <Badge variant="outline" className="text-xs bg-gray-50">Available</Badge> | |
| )} | |
| </div> | |
| </SelectItem> | |
| ))} | |
| </SelectGroup> | |
| </SelectContent> | |
| </Select> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| {/* Generation Parameters */} | |
| <Card> | |
| <CardHeader> | |
| <CardTitle className="text-base">Parameters</CardTitle> | |
| </CardHeader> | |
| <CardContent className="space-y-6"> | |
| {/* Temperature Slider */} | |
| <div> | |
| <div className="flex items-center justify-between mb-3"> | |
| <Label className="text-sm font-medium">Temperature</Label> | |
| <Badge variant="outline" className="text-xs"> | |
| {temperature} | |
| </Badge> | |
| </div> | |
| <Slider | |
| value={[temperature]} | |
| onValueChange={(value) => setTemperature(value[0])} | |
| max={2} | |
| min={0} | |
| step={0.1} | |
| className="w-full mb-3" | |
| /> | |
| <div className="flex justify-between text-xs text-gray-500 mb-2"> | |
| <span>0.0 (Focused)</span> | |
| <span>1.0 (Balanced)</span> | |
| <span>2.0 (Creative)</span> | |
| </div> | |
| <div className="text-xs text-muted-foreground bg-gray-50 p-2 rounded"> | |
| {temperature <= 0.3 | |
| ? "π― Very focused and deterministic responses" | |
| : temperature <= 0.7 | |
| ? "βοΈ Balanced creativity and consistency" | |
| : temperature <= 1.2 | |
| ? "π¨ More creative and varied responses" | |
| : "π Highly creative, unpredictable responses" | |
| } | |
| </div> | |
| </div> | |
| {/* Max Tokens Slider */} | |
| <div> | |
| <div className="flex items-center justify-between mb-3"> | |
| <Label className="text-sm font-medium">Max Tokens</Label> | |
| <Badge variant="outline" className="text-xs"> | |
| {maxTokens} | |
| </Badge> | |
| </div> | |
| <Slider | |
| value={[maxTokens]} | |
| onValueChange={(value) => setMaxTokens(value[0])} | |
| max={4000} | |
| min={50} | |
| step={50} | |
| className="w-full mb-3" | |
| /> | |
| <div className="flex justify-between text-xs text-gray-500 mb-2"> | |
| <span>50 (Short)</span> | |
| <span>1024 (Medium)</span> | |
| <span>4000 (Long)</span> | |
| </div> | |
| <div className="text-xs text-muted-foreground bg-gray-50 p-2 rounded"> | |
| {maxTokens <= 200 | |
| ? "π Brief responses, good for quick answers" | |
| : maxTokens <= 1000 | |
| ? "π Medium responses, balanced length" | |
| : maxTokens <= 2000 | |
| ? "π Long responses, detailed explanations" | |
| : "π Very long responses, comprehensive content" | |
| } | |
| </div> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| </> | |
| ) | |
| } | |