Skip to main content

Dead simple LLM fine-tuning with Unsloth

Project description

EasyFineTuner Banner

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

easyfinetuner-0.1.1.tar.gz (46.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

easyfinetuner-0.1.1-py3-none-any.whl (33.2 kB view details)

Uploaded Python 3

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

Hashes for easyfinetuner-0.1.1.tar.gz
Algorithm Hash digest
SHA256 ed83c7cde22d9333fdfe4b437edd26d3bba12cb42f676e167ea261a4974ae9cb
MD5 2c9a838a57d981aa4ab2088e2755c595
BLAKE2b-256 595fbcfcf63ec2ee09bbd33c8ba70a62daa737797ce136b321fd830c0aa1a1a6

See more details on using hashes here.

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

Hashes for easyfinetuner-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 21ded4c037614edddd76e92dad456db5fd43c5d458a67c814b17ca1b74da705b
MD5 33918c737cad8fed642ac1bab3e1538e
BLAKE2b-256 d77b573b2ddcbc022ad9a22215ff88337bc6094f3098b38e36a76e62b4227db4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page