Dead simple LLM fine-tuning with Unsloth
Project description
EasyFinetuner 🚀
Dead simple LLM fine-tuning with Unsloth
Reduce 50+ lines of complex code to ~5 lines. EasyFinetuner wraps Unsloth to make fine-tuning large language models accessible to beginners while remaining powerful for experts.
🌟 Features
- 🎯 Simple API: Fine-tune in 4 lines of code
- ⚡ Auto-Configuration: Automatically detects optimal settings based on your GPU and data
- 📊 Multi-Format Support: Works with JSON, JSONL, CSV, DataFrames, or HuggingFace datasets
- 🔧 Smart Templates: Auto-detects and applies the right prompt template (Alpaca, ChatML, etc.)
- 📈 Built-in Evaluation: Perplexity, BLEU, and ROUGE metrics
- 💾 Easy Export: One-line GGUF export for llama.cpp
- 💻 Memory Efficient: 4-bit quantization with automatic VRAM optimization
🚀 Quick Start
from easyfinetuner import FineTuner
# Load and train in 4 lines
tuner = FineTuner(model_name="unsloth/Qwen3-1.7B")
tuner.train(dataset="data.json", output_dir="my_model")
metrics = tuner.evaluate()
tuner.export_gguf(quantization="q4_k_m")
📦 Installation
pip install easyfinetuner
Or install from source:
git clone https://github.com/HariharanSuthan-A/easy-fine-tuner.git
cd easyfinetuner
pip install -e .
📝 Usage Guide
Basic Training
from easyfinetuner import FineTuner
# Initialize with any HuggingFace model
tuner = FineTuner(
model_name="unsloth/Qwen3-1.7B",
max_seq_length=2048,
load_in_4bit=True
)
# Train on your data
tuner.train(
dataset="path/to/train.json",
output_dir="./output",
num_epochs=3,
learning_rate=2e-4
)
Training Data Formats
EasyFinetuner accepts data in multiple formats:
JSON (List of objects):
[
{"instruction": "What is 2+2?", "input": "", "output": "4"},
{"instruction": "Capital of France?", "input": "", "output": "Paris"}
]
JSONL (One object per line):
{"input": "Hello", "output": "Hi there!"}
{"input": "How are you?", "output": "I'm doing well!"}
CSV:
input,output
"What is AI?","AI stands for Artificial Intelligence..."
Python List:
data = [
{"question": "What is Python?", "answer": "A programming language"},
{"question": "What is ML?", "answer": "Machine Learning"}
]
tuner.train(dataset=data)
Auto-Configuration
Let EasyFinetuner figure out the best settings:
tuner = FineTuner("unsloth/Qwen3-1.7B")
# All parameters set to "auto" - will be optimized for your GPU and data
tuner.train(
dataset="data.json",
num_epochs="auto", # Based on dataset size
learning_rate="auto", # Based on dataset size
batch_size="auto", # Based on available VRAM
lora_r="auto", # Based on model size
)
Manual Configuration
Take full control when needed:
tuner.train(
dataset="data.json",
output_dir="./output",
num_epochs=5,
learning_rate=2e-4,
batch_size=2,
lora_r=64,
gradient_accumulation_steps=4,
warmup_steps=100,
weight_decay=0.01,
)
Evaluation
# Evaluate on validation set
metrics = tuner.evaluate(metrics=["perplexity", "bleu", "rouge"])
# Evaluate on custom test set
metrics = tuner.evaluate(
test_dataset="test.json",
metrics=["perplexity"],
num_samples=100,
generate_report=True
)
print(f"Perplexity: {metrics['perplexity']:.2f}")
Inference
# Generate text
response = tuner.predict("What is machine learning?", max_new_tokens=256)
print(response)
# With custom generation parameters
response = tuner.predict(
"Explain quantum computing",
max_new_tokens=512,
temperature=0.8,
top_p=0.95
)
Export to GGUF
# Export for llama.cpp
tuner.export_gguf(quantization="q4_k_m")
# Available quantizations:
# - "q4_k_m": Balanced quality/size (recommended)
# - "q5_k_m": Better quality
# - "q8_0": Very high quality
# - "f16": Half precision, no quantization
# Export and upload to HuggingFace
tuner.export_gguf(
quantization="q4_k_m",
upload_to_hub=True,
hf_repo_id="username/my-model",
hf_token="your_hf_token"
)
🎓 Examples
Example 1: Question Answering
from easyfinetuner import FineTuner
# Prepare QA data
train_data = [
{"question": "What is Python?", "answer": "Python is a high-level programming language."},
{"question": "What is a neural network?", "answer": "A neural network is a computing system inspired by biological neural networks."},
# ... more examples
]
# Train
tuner = FineTuner("unsloth/Qwen3-1.7B")
tuner.train(
dataset=train_data,
output_dir="qa_model",
num_epochs=3
)
# Test
answer = tuner.predict("What is deep learning?")
print(answer)
Example 2: Instruction Following (Alpaca Format)
data = [
{
"instruction": "Summarize the following text.",
"input": "The quick brown fox jumps over the lazy dog.",
"output": "A fox jumps over a dog."
},
# ... more examples
]
tuner = FineTuner("unsloth/Qwen3-1.7B", template="alpaca")
tuner.train(dataset=data, output_dir="summarizer")
Example 3: Chat Format
data = [
{
"messages": [
{"role": "user", "content": "Hello!"},
{"role": "assistant", "content": "Hi there! How can I help you today?"}
]
},
# ... more examples
]
tuner = FineTuner("unsloth/Qwen3-1.7B", template="chatml")
tuner.train(dataset=data, output_dir="chatbot")
⚙️ Advanced Features
Custom Templates
from easyfinetuner import FineTuner
from easyfinetuner.data_processor import TEMPLATES
# Use built-in templates
tuner = FineTuner("unsloth/Qwen3-1.7B", template="alpaca") # or "chatml", "plain"
# Define custom template
TEMPLATES["my_template"] = "Instruction: {instruction}\nInput: {input}\nOutput: {output}"
tuner = FineTuner("unsloth/Qwen3-1.7B", template="my_template")
Resume Training
tuner.train(
dataset="data.json",
output_dir="./output",
resume_from_checkpoint="./output/checkpoint-500"
)
Save/Load Adapters
# Save only LoRA adapters (small, efficient)
tuner.save("path/to/adapters", save_adapter_only=True)
# Save full merged model (larger)
tuner.save("path/to/full_model", save_adapter_only=False)
# Load adapters into a new tuner
new_tuner = FineTuner("unsloth/Qwen3-1.7B")
new_tuner.load_adapters("path/to/adapters")
🛠️ Supported Models
EasyFinetuner works with any model supported by Unsloth, including:
- Qwen:
unsloth/Qwen3-1.7B,unsloth/Qwen3-4B,unsloth/Qwen3-8B - Llama:
unsloth/Llama-3.2-3B,unsloth/Llama-3.1-8B - Mistral:
unsloth/Mistral-7B-v0.3 - Gemma:
unsloth/gemma-2-2b,unsloth/gemma-2-9b - Phi:
unsloth/Phi-4,unsloth/Phi-3-mini-4k
💾 GPU Memory Requirements
| Model Size | 4-bit Training | 4-bit Inference |
|---|---|---|
| 1.7B | 4 GB | 2 GB |
| 3-4B | 6 GB | 3 GB |
| 7-8B | 10 GB | 5 GB |
| 14B | 18 GB | 9 GB |
🔧 Troubleshooting
Out of Memory Error
If you get OOM errors, try:
tuner.train(
dataset="data.json",
batch_size=1, # Reduce batch size
max_seq_length=1024, # Reduce sequence length
load_in_4bit=True, # Ensure 4-bit is enabled
gradient_accumulation_steps=8, # Increase to maintain effective batch
)
Slow Training
tuner.train(
dataset="data.json",
num_epochs=1, # Reduce epochs
batch_size=4, # Increase if VRAM allows
logging_steps=50, # Log less frequently
)
📚 API Reference
FineTuner Class
FineTuner(
model_name: str, # HuggingFace model name
max_seq_length: Union[int, str], # Max sequence length (auto)
load_in_4bit: bool = True, # Use 4-bit quantization
template: str = "auto", # Prompt template (auto)
)
.train(
dataset: Union[str, List, Dataset], # Training data
output_dir: str = "outputs", # Output directory
num_epochs: Union[int, str] = "auto", # Number of epochs
learning_rate: Union[float, str] = "auto",
batch_size: Union[int, str] = "auto",
lora_r: Union[int, str] = "auto",
validation_split: float = 0.1,
**kwargs
) -> Dict[str, Any]
.evaluate(
test_dataset: Optional[Dataset] = None,
metrics: List[str] = ["perplexity"],
num_samples: int = 100,
generate_report: bool = False
) -> Dict[str, Any]
.predict(
prompt: str,
max_new_tokens: int = 256,
temperature: float = 0.7,
**kwargs
) -> str
.export_gguf(
output_path: str = "model.gguf",
quantization: str = "q4_k_m",
upload_to_hub: bool = False,
hf_repo_id: str = None,
hf_token: str = None
) -> str
🤝 Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
📄 License
MIT License - see LICENSE for details.
🙏 Acknowledgments
- Built on Unsloth for efficient fine-tuning
- Uses TRL for training
- Inspired by the need for simpler LLM fine-tuning tools
Happy Fine-tuning! 🚀
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file easyfinetuner-0.1.1.tar.gz.
File metadata
- Download URL: easyfinetuner-0.1.1.tar.gz
- Upload date:
- Size: 46.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed83c7cde22d9333fdfe4b437edd26d3bba12cb42f676e167ea261a4974ae9cb
|
|
| MD5 |
2c9a838a57d981aa4ab2088e2755c595
|
|
| BLAKE2b-256 |
595fbcfcf63ec2ee09bbd33c8ba70a62daa737797ce136b321fd830c0aa1a1a6
|
File details
Details for the file easyfinetuner-0.1.1-py3-none-any.whl.
File metadata
- Download URL: easyfinetuner-0.1.1-py3-none-any.whl
- Upload date:
- Size: 33.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
21ded4c037614edddd76e92dad456db5fd43c5d458a67c814b17ca1b74da705b
|
|
| MD5 |
33918c737cad8fed642ac1bab3e1538e
|
|
| BLAKE2b-256 |
d77b573b2ddcbc022ad9a22215ff88337bc6094f3098b38e36a76e62b4227db4
|