Project

fine

0.0
The project is in a healthy, maintained state
A Ruby-native interface for fine-tuning machine learning models, starting with image classification using SigLIP2
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 13.0
~> 3.12
~> 1.50

Runtime

>= 5.0
>= 2.1
>= 0.17
 Project Readme

Fine

Fine-tune machine learning models with Ruby.

classifier = Fine::TextClassifier.new("distilbert-base-uncased")
classifier.fit(train_file: "reviews.jsonl", epochs: 3)
classifier.predict("This product is amazing!")
# => [{ label: "positive", score: 0.97 }]

I want to fine-tune...

Text classification (sentiment, spam, intent)

Classify text into categories—reviews, support tickets, chat messages.

classifier = Fine::TextClassifier.new("distilbert-base-uncased")
classifier.fit(train_file: "data/reviews.jsonl", epochs: 3)

classifier.predict("Terrible experience, waste of money")
# => [{ label: "negative", score: 0.94 }]

Full tutorial: Text Classification


Text embeddings for semantic search

Train embeddings for your domain—legal docs, support tickets, product catalog.

embedder = Fine::TextEmbedder.new("sentence-transformers/all-MiniLM-L6-v2")
embedder.fit(train_file: "data/pairs.jsonl", epochs: 3)

embedding = embedder.encode("How do I cancel my subscription?")

Full tutorial: Text Embeddings


Image classification

Classify images into categories (cats vs dogs, products, documents).

classifier = Fine::ImageClassifier.new("google/siglip2-base-patch16-224")
classifier.fit(train_dir: "data/train", val_dir: "data/val", epochs: 3)

classifier.predict("photo.jpg")
# => [{ label: "cat", score: 0.95 }]

Full tutorial: Image Classification


Image recognition for custom objects

Teach the model to recognize your products, logos, or custom objects.

classifier = Fine::ImageClassifier.new("google/siglip2-base-patch16-384") do |config|
  config.epochs = 5
  config.learning_rate = 1e-4
end

classifier.fit(train_dir: "products/train")
classifier.save("models/product_detector")

Full tutorial: Object Recognition


Image similarity search

Find visually similar images in your catalog.

encoder = model.encoder
embedding = encoder.call(image_tensor)
similarity = cosine_similarity(embedding1, embedding2)

Full tutorial: Similarity Search


LLMs (with LoRA)

Fine-tune Gemma, Llama, Qwen and other open models using LoRA—train only 0.5% of parameters.

model = Fine::Models::CausalLM.from_pretrained("google/gemma-3-1b-it")

# Apply LoRA - only 0.5% of params trainable
Fine::LoRA.apply(model, rank: 32, alpha: 64)
#   Trainable params: 5.96M (0.46%)

# Train on your data
trainer = Fine::Training::LLMTrainer.new(model, config, train_dataset: dataset)
trainer.fit

# Merge weights and save
Fine::LoRA.merge!(model)
model.save("my_model")

Full tutorial: LLM Fine-tuning | LoRA Tool Calling


Installation

gem 'fine'

Requires Ruby 3.1+, LibTorch, and libvips.

Full installation guide | Quickstart

Quick setup (macOS):

brew install pytorch libvips
bundle install

Supported Models

Text Classification

Model Parameters Speed Quality
distilbert-base-uncased 66M Fast Good
bert-base-uncased 110M Medium Better
microsoft/deberta-v3-small 44M Fast Great
microsoft/deberta-v3-base 86M Medium Best

Text Embeddings

Model Parameters Best For
sentence-transformers/all-MiniLM-L6-v2 22M Fast, general purpose
sentence-transformers/all-mpnet-base-v2 110M Better quality
BAAI/bge-small-en-v1.5 33M Retrieval optimized
BAAI/bge-base-en-v1.5 110M Best retrieval

Vision (SigLIP2)

Model Parameters Best For
google/siglip2-base-patch16-224 86M Quick experiments
google/siglip2-base-patch16-384 86M Good balance
google/siglip2-large-patch16-256 303M Maximum accuracy
google/siglip2-so400m-patch14-224 400M Best quality

LLMs

Model Parameters Best For
google/gemma-3-1b-it 1B Fast experiments, tool calling
meta-llama/Llama-3.2-1B 1B Fast experiments
google/gemma-3-4b-it 4B Good balance
Qwen/Qwen2-1.5B 1.5B Multilingual
mistralai/Mistral-7B-v0.1 7B Best quality

Configuration

Fine::TextClassifier.new("distilbert-base-uncased") do |config|
  config.epochs = 3
  config.batch_size = 16
  config.learning_rate = 2e-5
  config.max_length = 256

  config.on_epoch_end do |epoch, metrics|
    puts "Epoch #{epoch}: #{metrics[:accuracy]}"
  end
end

Export for Deployment

Export fine-tuned models to production formats.

ONNX - For ONNX Runtime, TensorRT, OpenVINO:

classifier.export_onnx("model.onnx")
embedder.export_onnx("embedder.onnx")

GGUF - For llama.cpp, ollama (LLMs only):

llm.export_gguf("model.gguf", quantization: :q4_0)

Full tutorial: Model Export

Roadmap

  • SigLIP2 image classification
  • Text classification (BERT, DeBERTa)
  • Text embedding models
  • LLM fine-tuning (Gemma, Llama, Qwen)
  • ONNX & GGUF export
  • LoRA fine-tuning
  • QLoRA (4-bit quantized LoRA)

Contributing

Bug reports and pull requests welcome at github.com/khasinski/fine.

License

MIT