Skip to main content

neotune

Simple LLM fine-tuning with LoRA and DeepSpeed.

Three inputs: a model, your datasets, and hyperparameters.

Installation

pip install neotune

With optional extras:

pip install "neotune[ray]"       # Ray distributed training
pip install "neotune[logging]"   # MLflow + Weights & Biases
pip install "neotune[all]"       # everything

Quick Start

from neotune import finetune

results = finetune(
    model="google/gemma-3-4b-pt",
    datasets={"train": train_ds, "validation": val_ds},
    hyperparameters={"learning_rate": 2e-4, "num_train_epochs": 3},
)

Each dataset is a HuggingFace Dataset with a "text" column containing fully-formatted prompt/response strings, or pre-tokenized columns (input_ids, attention_mask, labels).

Preparing Your Datasets

neotune expects you to bring your own HuggingFace Dataset objects.

From a HuggingFace dataset

from datasets import load_dataset
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("google/gemma-3-4b-pt")

ds = load_dataset("tatsu-lab/alpaca", split="train")

def format_example(example):
    messages = [
        {"role": "user", "content": example["instruction"]},
        {"role": "assistant", "content": example["output"]},
    ]
    return {"text": tokenizer.apply_chat_template(messages, tokenize=False)}

ds = ds.map(format_example, remove_columns=ds.column_names)
splits = ds.train_test_split(test_size=0.1, seed=42)

# splits["train"] and splits["test"] each have a "text" column

From a CSV file

from datasets import load_dataset
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("google/gemma-3-4b-pt")

ds = load_dataset("csv", data_files="data.csv", split="train")

def format_example(example):
    messages = [
        {"role": "user", "content": example["prompt"]},
        {"role": "assistant", "content": example["response"]},
    ]
    return {"text": tokenizer.apply_chat_template(messages, tokenize=False)}

ds = ds.map(format_example, remove_columns=ds.column_names)
splits = ds.train_test_split(test_size=0.1, seed=42)

API Reference

finetune(model, datasets, hyperparameters) -> dict

One-call convenience function. Returns test-set metrics if a "test" split was provided, otherwise an empty dict.

from neotune import finetune

results = finetune(
    model="google/gemma-3-4b-pt",
    datasets={"train": train_ds, "validation": val_ds, "test": test_ds},
    hyperparameters={"learning_rate": 2e-4},
)

NeoTune(model, datasets, hyperparameters)

Class-based API.

from neotune import NeoTune

nt = NeoTune(
    model="google/gemma-3-4b-pt",
    datasets={"train": train_ds, "validation": val_ds},
    hyperparameters={"num_train_epochs": 5, "output_dir": "./my-adapter"},
)

results = nt.train()

Parameters

model -- str HuggingFace model ID or local path.

datasets -- dict[str, Dataset] A dict of HuggingFace Dataset objects. "train" is required. "validation" and "test" are optional.

hyperparameters -- dict, optional Override any default. All keys are optional:

Key Default Description
Training
learning_rate 1e-4 Learning rate
num_train_epochs 3 Number of training epochs
batch_size 1 Per-device batch size
gradient_accumulation_steps 4 Gradient accumulation steps
warmup_ratio 0.03 Warmup ratio
weight_decay 0.01 Weight decay
bf16 True bfloat16 mixed precision
gradient_checkpointing False Gradient checkpointing
logging_steps 10 Log every N steps
eval_steps 50 Evaluate every N steps
save_steps 100 Checkpoint every N steps
save_total_limit 3 Max checkpoints to keep
LoRA
lora_r 16 LoRA rank
lora_alpha 32 LoRA alpha
lora_dropout 0.05 LoRA dropout
lora_target_modules "all-linear" Target modules (auto-detects all linear layers)
Output
output_dir "./adapter-output" Where to save the adapter
hf_repo None Push to HuggingFace Hub
DeepSpeed
ds_config None None (auto: DeepSpeed ZeRO-2 on multi-GPU, disabled on single GPU), "auto" (force ZeRO-2), False (force off), a file path, or a dict
Data
max_len 2048 Max sequence length
dataset_text_field "text" Column name for training text

Methods

  • .train() -> dict -- Fine-tune and return test metrics (if test split provided).
  • .tokenizer -- Access the underlying tokenizer.

Compute Environments

neotune auto-detects your hardware and launches training accordingly — same finetune() call everywhere:

Environment What happens
CPU Trains on CPU (float32)
Single CUDA GPU Single-GPU training (bf16)
Multi CUDA GPU Distributed training via accelerate launch + DeepSpeed ZeRO-2
Apple Silicon (MPS) MPS acceleration (fp16)

Multi-GPU works from scripts, notebooks, and the Python REPL — no need for torchrun or deepspeed CLI. neotune handles the distributed launch automatically.

Override with ds_config:

# Force DeepSpeed off
finetune(model, datasets, {"ds_config": False})

# Force DeepSpeed on (even on single GPU)
finetune(model, datasets, {"ds_config": "auto"})

# Custom DeepSpeed config
finetune(model, datasets, {"ds_config": "my_ds_config.json"})

Advanced Usage

Generative evaluation

from neotune.eval import generate_and_evaluate

results = generate_and_evaluate(
    model_id="google/gemma-3-4b-pt",
    adapter_dir="./my-adapter",
    test_ds=test_ds,
    prompt_col="instruction",
    label_col="expected_output",
)

Distributed training with DeepSpeed (CLI)

deepspeed --num_gpus 4 -m neotune.train --config config.yaml --mode train

Distributed training with Ray

python -m neotune.ray_train --config config.yaml --num_workers 4

Kubernetes (KubeRay)

See k8s/rayjob-lora-sft.yaml for a KubeRay RayJob template.

Environment Variables

Variable Description
HF_TOKEN HuggingFace access token (for gated models)
WANDB_API_KEY Weights & Biases API key (optional)

Create a .env file in your working directory:

HF_TOKEN=your_token_here
WANDB_API_KEY=your_wandb_key_here

License

MIT

Release files for neotune 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for neotune 1.1.1
File Size Uploaded
neotune-1.1.1.tar.gz 18.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for neotune 1.1.1
File Interpreter ABI Platform
neotune-1.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 39.0 kB

Release files / neotune-1.1.1.tar.gz

Download URL neotune-1.1.1.tar.gz
Size 18.3 kB
Tags Source
SHA-256 checksum
How to use checksums
b8fead0d75f207855d85d1cf6231dfc3ec8ac358aa9bc44f744bad4ceeda0db3
BLAKE2b-256 checksum
How to use checksums
2c4fa57f177701a113db95c63f0913f2f638e9b6ac7f1f8e1de6b6fa8de11665
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Release files / neotune-1.1.1-py3-none-any.whl

Download URL neotune-1.1.1-py3-none-any.whl
Size 20.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b6dd39dae819995c08b9aeec4e6acc4f0cbbb51b291e791ac5a45d6d386a713b
BLAKE2b-256 checksum
How to use checksums
14ab8846f57d170ac7ed931a6fb5165df363b32963152f2fbfd4f10ab17f9817
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Release history Release notifications | RSS feed

This release

1.1.1 This release

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page