Spaces:
Sleeping
Sleeping
import React, { useState, useEffect, useCallback } from 'react'; | |
const LLMTuner = () => { | |
const [datasets, setDatasets] = useState<string[]>([]); | |
const [selectedDataset, setSelectedDataset] = useState<string | null>(null); | |
const [trainingStatus, setTrainingStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle'); | |
const [trainingProgress, setTrainingProgress] = useState<number>(0); | |
const [trainingMessage, setTrainingMessage] = useState<string>(""); | |
const [modelParameters, setModelParameters] = useState({ | |
learningRate: 0.001, | |
batchSize: 32, | |
epochs: 10, | |
}); | |
const [showAdvancedOptions, setShowAdvancedOptions] = useState(false); | |
const handleDatasetUpload = useCallback((event: React.ChangeEvent<HTMLInputElement>) => { | |
if (!event.target.files) return; | |
const file = event.target.files[0]; | |
if (file) { | |
setDatasets(prev => [...prev, file.name]); | |
} | |
}, []); | |
const handleDatasetSelect = useCallback((dataset: string) => { | |
setSelectedDataset(dataset); | |
}, []); | |
const handleStartTraining = useCallback(async () => { | |
if (!selectedDataset) { | |
setTrainingMessage("Please select a dataset to start training."); | |
return; | |
} | |
setTrainingStatus('loading'); | |
setTrainingProgress(0); | |
setTrainingMessage("Training started... please wait"); | |
try { | |
// Simulate training process | |
for (let i = 0; i <= 100; i += 10) { | |
await new Promise(resolve => setTimeout(resolve, 500)); | |
setTrainingProgress(i); | |
} | |
setTrainingStatus('success'); | |
setTrainingMessage("Training completed successfully!"); | |
} catch (error) { | |
console.error("Training error:", error); | |
setTrainingStatus('error'); | |
setTrainingMessage("Training failed. Please try again."); | |
} | |
}, [selectedDataset]); | |
const handleParameterChange = useCallback((event: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => { | |
const { name, value } = event.target; | |
setModelParameters(prev => ({ ...prev, [name]: typeof value === 'string' && !isNaN(Number(value)) ? Number(value) : value })); | |
}, []); | |
const toggleAdvancedOptions = () => { | |
setShowAdvancedOptions(!showAdvancedOptions) | |
} | |
return ( | |
<div className="flex flex-col items-center p-8 bg-gray-100 min-h-screen"> | |
<h1 className="text-3xl font-bold mb-8 text-gray-800">LLM Fine-Tuner</h1> | |
<div className="bg-white rounded-xl shadow-md p-6 mb-8 w-full max-w-xl"> | |
<h2 className="text-xl font-semibold mb-4 text-gray-700">1. Upload Datasets</h2> | |
<div className="flex items-center mb-4"> | |
<input type="file" id="dataset-upload" className="hidden" onChange={handleDatasetUpload} /> | |
<label htmlFor="dataset-upload" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded cursor-pointer"> | |
Upload Dataset | |
</label> | |
<span className="ml-4 text-gray-600"> | |
{datasets.length > 0 ? `(${datasets.length} datasets uploaded)`: 'No datasets uploaded'} | |
</span> | |
</div> | |
{datasets.length > 0 && ( | |
<div className="mt-4"> | |
<h3 className="text-lg font-semibold mb-2 text-gray-700">Select a Dataset:</h3> | |
<ul className="space-y-2"> | |
{datasets.map((dataset, index) => ( | |
<li key={index} | |
className={`bg-gray-50 hover:bg-gray-200 px-3 py-2 rounded-md cursor-pointer transition-colors | |
${selectedDataset === dataset ? 'bg-gray-200' : ''}`} | |
onClick={() => handleDatasetSelect(dataset)}> | |
{dataset} | |
</li> | |
))} | |
</ul> | |
</div> | |
)} | |
</div> | |
<div className="bg-white rounded-xl shadow-md p-6 mb-8 w-full max-w-xl"> | |
<h2 className="text-xl font-semibold mb-4 text-gray-700">2. Configure Training Parameters</h2> | |
<div className="mb-4"> | |
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="learningRate"> | |
Learning Rate | |
</label> | |
<input | |
type="number" | |
id="learningRate" | |
name="learningRate" | |
value={modelParameters.learningRate} | |
onChange={handleParameterChange} | |
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" | |
/> | |
</div> | |
<div className="mb-4"> | |
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="batchSize"> | |
Batch Size | |
</label> | |
<input | |
type="number" | |
id="batchSize" | |
name="batchSize" | |
value={modelParameters.batchSize} | |
onChange={handleParameterChange} | |
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" | |
/> | |
</div> | |
<div className="mb-4"> | |
<button onClick={toggleAdvancedOptions} className="text-blue-500 hover:text-blue-700"> | |
{showAdvancedOptions ? "Hide Advanced Options" : "Show Advanced Options"} | |
</button> | |
</div> | |
{showAdvancedOptions && ( | |
<div className="mb-4"> | |
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="epochs"> | |
Epochs | |
</label> | |
<input | |
type="number" | |
id="epochs" | |
name="epochs" | |
value={modelParameters.epochs} | |
onChange={handleParameterChange} | |
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" | |
/> | |
</div> | |
)} | |
</div> | |
<div className="bg-white rounded-xl shadow-md p-6 mb-8 w-full max-w-xl"> | |
<h2 className="text-xl font-semibold mb-4 text-gray-700">3. Start Training</h2> | |
<button | |
onClick={handleStartTraining} | |
disabled={trainingStatus === 'loading'} | |
className={`bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline | |
${trainingStatus === 'loading' ? 'opacity-50 cursor-not-allowed' : ''}`} | |
> | |
{trainingStatus === 'loading' ? 'Training...' : 'Start Training'} | |
</button> | |
{trainingStatus !== 'idle' && ( | |
<div className="mt-4"> | |
<p className="text-gray-700 text-sm">{trainingMessage}</p> | |
{trainingStatus === 'loading' && ( | |
<div className="mt-2 bg-gray-200 rounded-full h-2"> | |
<div | |
className="bg-green-500 rounded-full h-2" | |
style={{ width: `${trainingProgress}%` }} | |
/> | |
</div> | |
)} | |
</div> | |
)} | |
</div> | |
</div> | |
); | |
}; | |
export default LLMTuner; |