tGu / trainer.js
TheGreatUnknown's picture
Create trainer.js
221214f verified
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;