diff --git a/.gitignore b/.gitignore
index 4e2e927..a4e8471 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,11 +12,12 @@ ModelForge/utilities/__pycache__/*
ModelForge/utilities/tests/
*.pyc
.env
-ModelForge/database/
-ModelForge/database/*
*.db
+*.sqlite
dist/
dist/*
ModelForge.egg-info/*
ModelForge.egg-info/
-*.egg-info
\ No newline at end of file
+*.egg-info
+*.lock
+unsloth_compiled_cache/*
\ No newline at end of file
diff --git a/Frontend/src/pages/FinetuningSettingsPage.jsx b/Frontend/src/pages/FinetuningSettingsPage.jsx
index 3b7b264..d6aa1c8 100644
--- a/Frontend/src/pages/FinetuningSettingsPage.jsx
+++ b/Frontend/src/pages/FinetuningSettingsPage.jsx
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
-import { config } from '../services/api';
+import { config, getSystemInfo, uploadDataset, startTraining } from '../services/api';
const FinetuneSettings = ({ defaultValues, updateSettings }) => {
const navigate = useNavigate();
@@ -10,17 +10,65 @@ const FinetuneSettings = ({ defaultValues, updateSettings }) => {
const [settingsUpdated, setSettingsUpdated] = useState(false);
const [activeTooltip, setActiveTooltip] = useState(null);
+ // New state for dynamic options
+ const [availableProviders, setAvailableProviders] = useState([]);
+ const [availableStrategies, setAvailableStrategies] = useState([]);
+ const [systemInfo, setSystemInfo] = useState(null);
+ const [isLoading, setIsLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ // Fetch system info on component mount
useEffect(() => {
- const fetchDefaultSettings = async () => {
+ const fetchSystemInfo = async () => {
try {
- const response = await fetch(`${config.baseURL}/finetune/load_settings`);
- if (!response.ok) throw new Error('Failed to fetch settings');
+ setIsLoading(true);
+ const info = await getSystemInfo();
+ console.log("Fetched system info:", info);
+
+ setSystemInfo(info);
+ setAvailableProviders(info.available_providers || ['huggingface']);
+ setAvailableStrategies(info.available_strategies || ['sft']);
- const data = await response.json();
- console.log("Fetched default values:", data.default_values);
- defaultValues = data.default_values;
- // Update form state with fetched values
- setFormState(data.default_values);
+ setIsLoading(false);
+ } catch (err) {
+ console.error("Error fetching system info:", err);
+ setError("Failed to load system information");
+ // Fallback to defaults
+ setAvailableProviders(['huggingface']);
+ setAvailableStrategies(['sft']);
+ setIsLoading(false);
+ }
+ };
+
+ fetchSystemInfo();
+ }, []);
+
+ useEffect(() => {
+ const fetchDefaultSettings = async () => {
+ try {
+ // Fetch default settings
+ const settingsResponse = await fetch(`${config.baseURL}/finetune/load_settings`);
+ if (!settingsResponse.ok) throw new Error('Failed to fetch settings');
+ const settingsData = await settingsResponse.json();
+ console.log("Fetched default values:", settingsData.default_values);
+
+ // Fetch session data (task, model_name)
+ const sessionResponse = await fetch(`${config.baseURL}/finetune/session`);
+ if (!sessionResponse.ok) throw new Error('Failed to fetch session');
+ const sessionData = await sessionResponse.json();
+ console.log("Fetched session data:", sessionData);
+
+ // Merge defaults with session data
+ const mergedState = {
+ ...settingsData.default_values,
+ task: sessionData.task,
+ model_name: sessionData.selected_model,
+ compute_specs: settingsData.compute_profile || 'low_end',
+ };
+
+ console.log("Merged form state:", mergedState);
+ defaultValues = mergedState;
+ setFormState(mergedState);
} catch (err) {
console.error("Error fetching settings:", err);
}
@@ -35,6 +83,13 @@ const FinetuneSettings = ({ defaultValues, updateSettings }) => {
if (defaultValues) {
// Create a deep copy to break any references
const values = JSON.parse(JSON.stringify(defaultValues));
+
+ // Set defaults for new fields if not present
+ if (!values.provider) values.provider = 'huggingface';
+ if (!values.strategy) values.strategy = 'sft';
+ if (values.eval_split === undefined) values.eval_split = 0.2;
+ if (values.eval_steps === undefined) values.eval_steps = 100;
+
console.log("Setting form values to:", values);
setFormState(values);
}
@@ -70,7 +125,7 @@ const FinetuneSettings = ({ defaultValues, updateSettings }) => {
const updatedState = {
...formState,
use_4bit: value === '4bit',
- load_in_8bit: value === '8bit',
+ use_8bit: value === '8bit',
quantization: value
};
@@ -79,41 +134,97 @@ const FinetuneSettings = ({ defaultValues, updateSettings }) => {
const handleSubmit = async (e) => {
e.preventDefault();
+
+ try {
+ setError(null);
+
+ // Validate required fields
+ if (!formState.task || !formState.model_name) {
+ setError("Missing required fields. Please go back and complete previous steps.");
+ return;
+ }
+
+ // Step 1: Upload dataset if provided
+ if (selectedFile) {
+ console.log("Uploading dataset...");
+ const uploadResponse = await uploadDataset(selectedFile, formState);
+ console.log("Dataset uploaded:", uploadResponse);
+
+ // Update form state with the uploaded file path
+ formState.dataset = uploadResponse.file_path;
+ } else {
+ throw new Error("Please select a dataset file");
+ }
- // Create FormData to send multipart data
- const formData = new FormData();
-
- // Append the selected file
- if (selectedFile) {
- formData.append("json_file", selectedFile, selectedFile.name);
- }
-
- // Append settings as a JSON string
- formData.append("settings", JSON.stringify(formState));
-
- console.log("Sending data to server:",JSON.stringify(formState));
+ // Step 2: Prepare training configuration
+ const trainingConfig = {
+ // Required fields
+ task: formState.task,
+ model_name: formState.model_name,
+ dataset: formState.dataset,
+ compute_specs: formState.compute_specs || 'low_end',
+
+ // Provider and strategy (NEW)
+ provider: formState.provider || 'huggingface',
+ strategy: formState.strategy || 'sft',
+
+ // LoRA settings
+ lora_r: formState.lora_r || 16,
+ lora_alpha: formState.lora_alpha || 32,
+ lora_dropout: formState.lora_dropout || 0.1,
+
+ // Quantization settings
+ use_4bit: formState.use_4bit !== undefined ? formState.use_4bit : true,
+ use_8bit: formState.use_8bit || false,
+ bnb_4bit_compute_dtype: formState.bnb_4bit_compute_dtype || 'float16',
+ bnb_4bit_quant_type: formState.bnb_4bit_quant_type || 'nf4',
+ use_nested_quant: formState.use_nested_quant || false,
+
+ // Training precision
+ fp16: formState.fp16 || false,
+ bf16: formState.bf16 || false,
+
+ // Training hyperparameters
+ num_train_epochs: formState.num_train_epochs || 1,
+ per_device_train_batch_size: formState.per_device_train_batch_size || 1,
+ per_device_eval_batch_size: formState.per_device_eval_batch_size || 1,
+ gradient_accumulation_steps: formState.gradient_accumulation_steps || 4,
+ gradient_checkpointing: formState.gradient_checkpointing !== undefined ? formState.gradient_checkpointing : true,
+ max_grad_norm: formState.max_grad_norm || 0.3,
+ learning_rate: formState.learning_rate || 0.0002,
+ weight_decay: formState.weight_decay || 0.001,
+ optim: formState.optim || 'paged_adamw_32bit',
+ lr_scheduler_type: formState.lr_scheduler_type || 'cosine',
+ max_steps: formState.max_steps || -1,
+ warmup_ratio: formState.warmup_ratio || 0.03,
+ group_by_length: formState.group_by_length !== undefined ? formState.group_by_length : true,
+ packing: formState.packing || false,
+
+ // Sequence settings
+ max_seq_length: formState.max_seq_length || null,
+
+ // Evaluation settings (NEW)
+ eval_split: formState.eval_split !== undefined ? formState.eval_split : 0.2,
+ eval_steps: formState.eval_steps || 100,
+ };
- try {
- const response = await fetch(`${config.baseURL}/finetune/load_settings`, {
- method: 'POST',
- body: formData,
- });
+ console.log("Starting training with config:", trainingConfig);
- if (!response.ok) {
- throw new Error(`Server error: ${response.status}`);
- }
+ // Step 3: Start training
+ const trainingResponse = await startTraining(trainingConfig);
+ console.log("Training started:", trainingResponse);
- const responseGet = await fetch(`${config.baseURL}/finetune/start`, {
- method: 'GET',
- });
- console.log("Response from GET request:", responseGet);
+ setSettingsUpdated(true);
+
+ // Navigate to loading page after short delay
setTimeout(() => {
- navigate('/finetune/loading'); // change here
+ navigate('/finetune/loading');
}, 1000);
} catch (error) {
console.error("Error submitting form:", error);
- alert("Failed to update settings.");
+ setError(error.message || "Failed to start training");
+ alert(`Failed to start training: ${error.message}`);
}
};
@@ -121,6 +232,8 @@ const FinetuneSettings = ({ defaultValues, updateSettings }) => {
const tooltips = {
task: "What you want your AI to be good at doing",
model_name: "The base AI model you're customizing",
+ provider: "Model provider (HuggingFace for standard, Unsloth for 2x faster training)",
+ strategy: "Training method (SFT for basic, RLHF for preference learning, DPO for direct optimization, QLoRA for memory efficiency)",
gpu: "The graphics card that will run your training",
ram: "Computer memory available for training",
num_train_epochs: "How many times the AI will see your training data",
@@ -133,7 +246,23 @@ const FinetuneSettings = ({ defaultValues, updateSettings }) => {
quantization: "Reduces model size to fit in memory",
bnb_4bit_compute_dtype: "Technical setting for calculation precision",
optim: "Method used to update the model during training",
- lr_scheduler_type: "How learning speed changes during training"
+ lr_scheduler_type: "How learning speed changes during training",
+ eval_split: "Percentage of data to use for validation (0-1)",
+ eval_steps: "How often to evaluate the model during training"
+ };
+
+ // Provider descriptions
+ const providerDescriptions = {
+ huggingface: "Standard HuggingFace Hub models",
+ unsloth: "Optimized for 2x faster training with lower memory"
+ };
+
+ // Strategy descriptions
+ const strategyDescriptions = {
+ sft: "Supervised Fine-Tuning - Standard approach with LoRA",
+ rlhf: "Reinforcement Learning from Human Feedback - Preference-based training",
+ dpo: "Direct Preference Optimization - Simpler alternative to RLHF",
+ qlora: "Quantized LoRA - Memory-efficient training with 4-bit quantization"
};
// Tooltip display component
@@ -157,13 +286,36 @@ const FinetuneSettings = ({ defaultValues, updateSettings }) => {
);
+ if (isLoading) {
+ return (
+
+
+
+
Loading system information...
+
+
+ );
+ }
+
return (
Finetuning Settings
Configure your model training parameters
+
+ {systemInfo && (
+
+ Available: {availableProviders.length} provider(s), {availableStrategies.length} strategy(ies)
+
+ )}
+ {error && (
+
+ Error: {error}
+
+ )}
+
{settingsUpdated && (
Settings updated successfully! Redirecting...
@@ -212,6 +364,64 @@ const FinetuneSettings = ({ defaultValues, updateSettings }) => {
+ {/* Provider and Strategy Selection */}
+
+
Provider & Strategy
+
+
+
+
+
+
+ {formState.provider && providerDescriptions[formState.provider] && (
+
+ {providerDescriptions[formState.provider]}
+
+ )}
+
+
+
+
+
+
+
+ {formState.strategy && strategyDescriptions[formState.strategy] && (
+
+ {strategyDescriptions[formState.strategy]}
+
+ )}
+
+
+
+
{/* Basic Settings */}
Basic Settings
@@ -324,6 +534,55 @@ const FinetuneSettings = ({ defaultValues, updateSettings }) => {
+ {/* Evaluation Settings */}
+
+
Evaluation Settings
+
+
+
+
+
+
+
+ {Math.round((formState.eval_split || 0.2) * 100)}% of data for validation
+
+
+
+
+
+
+
+
+
+ Evaluate every {formState.eval_steps || 100} training steps
+
+
+
+
+
{/* Advanced Settings */}
@@ -441,7 +701,7 @@ const FinetuneSettings = ({ defaultValues, updateSettings }) => {