Levi / frontend /src /components /Settings.tsx
Manish Kumar
chnage model
0a7f861
Raw
History Blame Contribute Delete
8.43 kB
import React, { useState } from 'react';
import { Save, CheckCircle2, AlertTriangle, RefreshCw } from 'lucide-react';
import type { AppSettings, ModelInfo } from '../types';
interface SettingsProps {
settings: AppSettings;
updateSettings: (newSettings: Partial<AppSettings>) => void;
clearHistory: () => void;
modelInfo: ModelInfo | null;
}
export const Settings: React.FC<SettingsProps> = ({
settings,
updateSettings,
clearHistory,
modelInfo,
}) => {
const [saveSuccess, setSaveSuccess] = useState(false);
const [resetting, setResetting] = useState(false);
const [confirmClear, setConfirmClear] = useState(false);
const handleSave = () => {
setSaveSuccess(true);
setTimeout(() => setSaveSuccess(false), 2000);
};
const handleClearHistory = () => {
if (confirmClear) {
setResetting(true);
setTimeout(() => {
clearHistory();
setConfirmClear(false);
setResetting(false);
alert('Conversation history cleared.');
}, 800);
} else {
setConfirmClear(true);
}
};
return (
<div className="flex-1 overflow-y-auto bg-[#090810] p-6 lg:p-8 font-sans select-none">
<div className="max-w-6xl grid grid-cols-1 lg:grid-cols-5 gap-8 items-start">
<div className="lg:col-span-3 space-y-5 bg-[#131121] border border-[#1d1b2e] p-6 rounded-2xl">
<div className="border-b border-[#1d1b2e] pb-4">
<h2 className="text-md font-bold text-white tracking-tight">Generation Settings</h2>
<p className="text-[10px] text-[#9d99b3] mt-0.5">Configure how the AI model generates responses.</p>
</div>
<div className="space-y-5 pt-1">
<div className="space-y-1.5">
<label className="text-[10px] font-bold text-[#9d99b3] uppercase tracking-wider">Model</label>
<div className="bg-[#090810] border border-[#1d1b2e] text-xs text-white rounded-xl px-3 py-2.5 font-mono">
SmolLM2-360M-Instruct-Q4_K_M.gguf
</div>
</div>
<div className="h-px bg-[#1d1b2e] my-2"></div>
<div className="space-y-2">
<div className="flex justify-between text-xs font-semibold">
<span className="text-white">Temperature</span>
<span className="text-primary font-mono text-[11px] bg-primary/10 px-2 py-0.5 rounded">{settings.temperature}</span>
</div>
<input
type="range" min="0.1" max="1.5" step="0.1"
value={settings.temperature}
onChange={(e) => updateSettings({ temperature: parseFloat(e.target.value) })}
className="w-full accent-primary h-1 bg-[#090810] rounded-lg appearance-none cursor-pointer"
/>
</div>
<div className="space-y-2">
<div className="flex justify-between text-xs font-semibold">
<span className="text-white">Max Tokens</span>
<span className="text-primary font-mono text-[11px] bg-primary/10 px-2 py-0.5 rounded">{settings.maxTokens}</span>
</div>
<input
type="range" min="64" max="2048" step="64"
value={settings.maxTokens}
onChange={(e) => updateSettings({ maxTokens: parseInt(e.target.value) })}
className="w-full accent-primary h-1 bg-[#090810] rounded-lg appearance-none cursor-pointer"
/>
</div>
<div className="space-y-2">
<div className="flex justify-between text-xs font-semibold">
<span className="text-white">Top P</span>
<span className="text-primary font-mono text-[11px] bg-primary/10 px-2 py-0.5 rounded">{settings.topP}</span>
</div>
<input
type="range" min="0.1" max="1.0" step="0.05"
value={settings.topP}
onChange={(e) => updateSettings({ topP: parseFloat(e.target.value) })}
className="w-full accent-primary h-1 bg-[#090810] rounded-lg appearance-none cursor-pointer"
/>
</div>
<div className="h-px bg-[#1d1b2e] my-2"></div>
<div className="flex items-center justify-between py-1.5">
<div className="space-y-0.5">
<label className="text-xs font-bold text-white" htmlFor="stream-switch">Stream Response</label>
<p className="text-[10px] text-[#9d99b3]">Stream tokens as they are generated.</p>
</div>
<input type="checkbox" id="stream-switch"
checked={settings.streaming}
onChange={(e) => updateSettings({ streaming: e.target.checked })}
className="w-4.5 h-4.5 accent-primary cursor-pointer"
/>
</div>
<div className="flex items-center justify-end pt-3">
<button onClick={handleSave}
className="flex items-center justify-center gap-2 px-5 py-2.5 bg-[#6344d5] hover:bg-[#6344d5]/95 text-white font-bold text-xs rounded-xl cursor-pointer transition-all"
>
{saveSuccess ? <><CheckCircle2 size={13} /><span>Saved</span></> : <><Save size={13} /><span>Save Settings</span></>}
</button>
</div>
</div>
</div>
<div className="lg:col-span-2 space-y-6">
<div className="bg-[#131121] border border-[#1d1b2e] p-5 rounded-2xl space-y-4">
<h3 className="text-xs font-bold text-white uppercase tracking-wider border-b border-[#1d1b2e] pb-3">Model Information</h3>
<div className="space-y-3.5 text-xs select-none">
<div className="flex justify-between">
<span className="text-[#9d99b3]">Model</span>
<span className="font-semibold text-white font-mono text-[11px]">{modelInfo?.model_name || 'SmolLM2-360M-Instruct-Q4_K_M'}</span>
</div>
<div className="flex justify-between">
<span className="text-[#9d99b3]">Status</span>
<span className="font-semibold text-emerald-500 text-[11px]">{modelInfo?.status || 'loaded'}</span>
</div>
<div className="flex justify-between">
<span className="text-[#9d99b3]">Quantization</span>
<span className="font-semibold text-white font-mono text-[11px]">Q4_K_M</span>
</div>
<div className="flex justify-between">
<span className="text-[#9d99b3]">Disk Size</span>
<span className="font-semibold text-white font-mono text-[11px]">~180 MB</span>
</div>
</div>
</div>
{/* Danger zone log clear button */}
<div className="bg-[#131121] border border-[#1d1b2e] p-5 rounded-2xl space-y-3 select-none">
<h3 className="text-xs font-bold text-destructive uppercase tracking-wider flex items-center gap-1.5">
<AlertTriangle size={14} />
Reset Cache
</h3>
<button
onClick={handleClearHistory}
disabled={resetting}
className={`w-full flex items-center justify-center gap-2 px-3 py-2.5 border rounded-xl font-bold text-xs transition-all cursor-pointer ${
confirmClear
? 'bg-destructive hover:bg-destructive/90 text-destructive-foreground border-transparent animate-pulse'
: 'bg-destructive/10 hover:bg-destructive/20 border-destructive/20 text-destructive'
}`}
>
{resetting ? (
<>
<RefreshCw size={13} className="animate-spin" />
<span>Reseting...</span>
</>
) : (
<>
<span>{confirmClear ? 'Confirm Reset' : 'Reset Database Records'}</span>
</>
)}
</button>
{confirmClear && !resetting && (
<button
onClick={() => setConfirmClear(false)}
className="w-full text-center text-[10px] hover:underline text-muted-foreground block py-1 cursor-pointer"
>
Cancel
</button>
)}
</div>
</div>
</div>
</div>
);
};