Tools and utilities for fast prototyping of machine learning ideas!
Project description
Yumbox 🍱
Yadgiri Machine Toolbox — A very yummy project! (Yadgiri is Persian for "learning".)
What is Yumbox?
Yumbox is a Machine Learning reusable toolbox to help bootstrap ML projects as quickly as possible! It follows the best practices I have accumulated over the years, from ensuring reproducibility and tracking experiments to following DRY (Don't Repeat Yourself) and VC (Version Control) on code/data principles. This project also specially focuses on Semantic Similarity, Classification, Information Retrieval, and the intersection of the three: Entity Resolution (and Entity Matching).
Why Yumbox came to be?
I found myself reusing the same classes and functions in my projects over the years, from my university days (pre-LLLM chatbot era) to this day, so I decided to create this project to gather all these proven functionalities, provide standard interfaces for them, and make them freely available to help everyone facilitate fast prototyping on ML projects.
How Yumbox came to be!
I gradually started refactoring the classes and functions from the projects I was working on in the industry and the university and I added them to Yumbox. I still continue to do so, when I find a highly valuable functionality that can be reused and shared with other projects. Since the things covered in this project have vastly different scopes, I follow a dynamic import paradigm so you only have to install the dependencies required for the functionality neede. I will later make these dynamic imports, lazy imports, just as popular libraries like HuggingFace's transformers do.
You can install this project using
pip install yumbox
pip install yumbox[faiss] # Installs FAISS dependency
⚠️ Heads up: Yumbox is currently in pre-release stage. I heavily use this repo in my projects and I try to not make breaking changes, but still, you should expect things to break, APIs to change, and documentation to play catch-up. Not all functionalities are fully tested yet.
🗂️ Project Structure
yumbox/
├── cache/ # 🔄 Caching decorators & storage backends (pickle, LMDB, Redis, FAISS)
├── config/ # ⚙️ Global config (BFG) + production-ready logger setup
├── data/ # 📦 Flexible Datasets, Samplers & training utilities for PyTorch
├── factory/ # 🏭 FAISS index builders, PCA, clustering, similarity computation
├── metrics/ # 📊 Classification, retrieval metrics + MLflow-ready plotting
├── mlflow/ # 🧪 Experiment tracking, checkpoint management, multi-run analysis
├── nlp/ # ✂️ Multilingual (EN/FA) text preprocessing, tokenization, analysis
├── parse/ # 🕵️ Runtime dependency analysis & import tracing
├── scraper/ # 🕷️ HTML parsing, text extraction, parallel image downloading
├── scripts/ # 🛠️ CLI tools for MLflow analysis & checkpoint cleanup
└── vectors/ # 🔍 Vector search, feature fusion, array utilities
🚀 Quick Start Examples
Cache results with one line
from yumbox.cache import cache
@cache # Auto-saves to BFG["cache_dir"]/{func_name}.pkl
def expensive_feature_extraction(data):
return heavy_computation(data)
# First call: runs computation, saves result
# Subsequent calls: loads from cache instantly ✨
Setup logging + config in 3 lines
from yumbox.config import BFG, setup_logger
BFG["cache_dir"] = "~/.cache/yumbox" # Auto-creates directory
logger = setup_logger(
name="my_project",
path="./logs", # Save logs to file
capture_libs=["torch"], # Also log PyTorch messages
suppress_libs=["httpcore"] # Silence noisy dependencies
)
logger.info("Ready to yum! 🍱")
Build a FAISS index for cosine search
import numpy as np
from yumbox.factory import build_index, pca_faiss
from yumbox.vectors import normalize_vector
# Your embeddings
embeddings = np.random.randn(10000, 768).astype(np.float32)
# Option 1: Quick flat index (exact search)
index = build_index(normalize_vector(embeddings)) # Inner product = cosine for unit vectors
# Option 2: PCA reduction + HNSW for speed
embeddings_reduced = pca_faiss(embeddings, n_components=128)
index = factory.FaissIndexBuilder().build_hnsw_index(
normalize_vector(embeddings_reduced),
M=32, efConstruction=200
)
# Search
distances, indices = index.search(query_vectors, k=10)
Preprocess multilingual text
from yumbox.nlp import Preprocessor
# English + Persian text cleaning
preproc = Preprocessor(
remove_punctuation=True,
remove_en_stopwords=True,
remove_fa_stopwords=True,
normalize_fa_chars=True, # Arabic→Farsi character mapping
do_hard_limit=True, # Filter words by length
low_hard_limit=3,
high_hard_limit=26,
)
clean_text = preproc("This is a test! این یک تست است. 🎉")
# → "this test تست"
Analyze MLflow experiments from CLI
# Compare validation loss across experiments
metrics-cli compare-experiments \
--storage-path ./mlruns \
--experiment-names baseline_v1 improved_model \
--metric val_loss \
--mode epoch \
--output-file loss_comparison.png
# Find best-performing runs
metrics-cli best-metrics \
--storage-path ./mlruns \
--experiment-names "exp_.*_bert" \
--metrics f1_score inference_time \
--min-or-max max min \
--output-csv best_runs.csv
🧩 Module Highlights
cache/ — Caching That Just Works
- Decorators:
@cache,@np_cache,@timed_cache,@async_cache,@retry - Backends: pickle, NumPy
.npz, HDF5, LMDB, Redis, FAISS indices, safetensors - Smart features: kwargs-based keys, hash-based keys, lazy loading, offset tracking for pagination
config/ — Logging & Configuration
BFG: Global config store (your own configs +cache_dirfor enabling/disabling cache functionalities of yumbox)setup_logger(): Color-coded console output, file logging, library capture/suppression, print redirection- Helpers:
execution_wrapper(auto-timing + error logging),main_run,log_df_info
data/ — Datasets & Training Utilities
- FlexibleDataset: Mode-aware (
text/image/text_image) datasets with transform pipelines - Specialized datasets:
WebImgDataset,TextDataset,TFDocumentDataset,ZeroshotDataset - Samplers:
ContrastiveSampler,TripletSampler,SiameseSampler,ClusterSamplerfor advanced training strategies
factory/ — FAISS & Vector Processing
- Index builders: Flat, IVF, HNSW, PQ, IVFPQ with GPU support
- Utilities:
pca_faiss,kmeans_faiss,self_similarity FaissIndexBuilder: Unified API for production-ready index construction
metrics/ — Evaluation Made Simple
- Classification:
classification_scores,extended_classification_scoreswith FPR/FNR - Retrieval:
mean_ir_scoresfor P@k, MAP, MRR, NDCG - Visualization: PR/ROC curves auto-logged to MLflow
- Utilities:
AverageMeterfor training loops,cosine_simfor tensor similarity
mlflow/ — Experiment Tracking & Checkpoint Management
- Logging:
log_config,log_scores_dict, recursive OmegaConf param logging - Analysis:
process_experiment_metrics,plot_metric_across_experiments,find_best_metrics - Checkpoint helpers: Intelligent cleanup based on metric performance (
manage-checkpointsCLI) - Export:
export_mlflow_data_with_flatteningfor CSV analysis
nlp/ — Multilingual Text Preprocessing
Preprocessor: Flag-driven pipeline for English/Persian text cleaning- Unicode utilities: Character normalization, accent stripping, CJK removal, range-based filtering
- Analysis:
MapRedfor frequency counting,defaultnamefor alias resolution/entity clustering
parse/ — Dependency Analysis
analyze_dependencies(): Runtime import tracing vs. installed/declared packages- Use cases: Generate minimal
requirements.txt, audit Docker images, CI/CD dependency checks
scraper/ — Web Scraping Utilities
- HTML parsing:
parse_html,html_to_text, enhancedMySelectorwith auto-decoding ImageDownloader: Parallel downloading with PIL corruption checks, custom DNS resolution, quality filtering
scripts/ — CLI Tools
metrics-cli: Subcommands for experiment analysis, comparison, checkpoint management, best-run discovery- Help system:
metrics-cli help patternsfor usage examples, troubleshooting guides
vectors/ — Vector Operations & Feature Fusion
- Search:
topk()with parallel FAISS querying,nested_topk()for hierarchical retrieval - Normalization:
normalize_vector()for NumPy/Torch tensors - Feature fusion:
cat_feats,mult_feats,sum_feats,diff_featswith missing-value handling - Utilities:
reconstruct_original_index()for restoring filtered arrays
🔁 Common Workflows
🔄 Incremental Embedding Pipeline
from yumbox.cache import np_cache_kwargs_hash # or @cache for pickle-based caching
from yumbox.factory import build_index
from yumbox.vectors import normalize_vector
import numpy as np
# 1. Setup cache directory (used by all @*cache decorators)
from yumbox.config import BFG
BFG["cache_dir"] = "~/.cache/my_project" # Auto-creates if needed
# 2. Decorate your heavy inference function — caching is automatic!
@np_cache_kwargs_hash # Caches dict[str, np.ndarray] with hash-based keys
def compute_embedding(image_path: str, model_name: str = "default", cache_kwargs: list = None, **kwargs):
"""
Heavy embedding computation — automatically cached by (image_path, model_name).
Returns dict for np_cache compatibility.
"""
# This only runs if cache miss!
img = load_and_preprocess(image_path) # Your image loading logic
emb = get_model(model_name)(img) # Your model inference
return {"embedding": emb.squeeze().cpu().numpy()} # Must return dict for np_cache
# 3. Process your dataset — no manual cache management needed!
embeddings = {}
for hash_key, img_path in zip(df["hash"], df["path"]):
# Automatic cache check: if (img_path, model_name) was computed before, loads instantly
result = compute_embedding(
img_path,
model_name="vit_base",
cache_kwargs=["image_path", "model_name"] # These kwargs affect cache key
)
embeddings[hash_key] = result["embedding"]
# 4. Build search index from cached embeddings
embedding_matrix = np.array(list(embeddings.values()))
index = build_index(normalize_vector(embedding_matrix)) # Cosine similarity via IP
faiss.write_index(index, "search_index.faiss")
# ✨ Next run: All previously computed embeddings load from cache in milliseconds!
📊 End-to-End Experiment Tracking
from yumbox.config import BFG, setup_logger, execution_wrapper
from yumbox.mlflow import log_config, log_scores_dict
import mlflow
# 1. Global setup
BFG["cache_dir"] = "./cache"
logger = setup_logger("my_experiment", path="./logs")
# 2. Wrap main logic for auto-timing + error logging
@execution_wrapper
def train(cfg):
with mlflow.start_run(run_name=cfg.run_name):
# Log config recursively
log_config(cfg)
# Training loop
for epoch in range(cfg.epochs):
# ... train ...
# Log metrics with step
val_metrics = evaluate(model, val_loader)
log_scores_dict(val_metrics, name="val", step=epoch)
# Save checkpoint with metric-based naming
if val_metrics["f1"] > best_f1:
ckpt_path = f"./checkpoints/epoch{epoch}_f1{val_metrics['f1']:.3f}.pt"
torch.save(model.state_dict(), ckpt_path)
mlflow.log_param("best_checkpoint", ckpt_path)
best_f1 = val_metrics["f1"]
# 3. Run with config
if __name__ == "__main__":
from omegaconf import OmegaConf
cfg = OmegaConf.load("configs/exp.yaml")
train(cfg)
🌍 Multilingual Text Processing Pipeline
from yumbox.nlp import Preprocessor
import pandas as pd
# Configure ONE preprocessor for your dataset's language mix
# Enable FA flags only if your data contains Persian/Farsi text
preproc = Preprocessor(
# === Language-agnostic cleaning (always useful) ===
remove_punctuation=True,
strip_accents=True, # é → e, ü → u
remove_cjk=True, # Remove Chinese/Japanese/Korean spam
remove_ctrl_chars=True, # Strip Unicode control/format chars
remove_parentheticals=True, # Remove text in () or []
do_hard_limit=True, # Filter words by length
low_hard_limit=3,
high_hard_limit=26,
# === Farsi/Persian support (enable if your data has FA text) ===
normalize_fa_chars=True, # Map Arabic variants → Farsi (ه→ه, ی→ی)
remove_fa_stopwords=True, # Remove common Farsi stopwords via hazm
do_fa_normalizer=True, # Apply hazm.Normalizer (spacing, digit conversion)
fa_tokenizer=True, # Use hazm.word_tokenize (script-aware splitting)
# === English support ===
remove_en_stopwords=True, # Remove NLTK English stopwords
do_en_normalizer=True, # Lowercase text
do_en_lemmatizer=True, # WordNet lemmatization
en_lemmatize_method="known", # POS-aware lemmatization for better accuracy
)
# Use the SAME preprocessor for all text — no language detection needed!
# The preprocessor gracefully handles monolingual or mixed-language input
df["clean_text"] = df["raw_text"].apply(preproc)
# Example outputs:
# "This is a test! 🎉" → "this test"
# "Mixed: hello و دنیا" → "mixed hello دنیا" (both languages processed)
🤝 Contributing
Yumbox thrives on community contributions! Here's how to help:
🐛 Found a bug?
- Check existing issues first
- Create a new issue with:
- Minimal reproducible example
- Expected vs. actual behavior
- Your environment (
python --version,pip list)
💡 Have an idea?
- Open a discussion issue to brainstorm
- Think of: new caching backends, more samplers, additional metrics, CLI enhancements
- What to be cautious about: breaking API changes, heavy new dependencies
🔧 Want to code?
# Fork and clone
git clone https://github.com/eshteharipour/yumbox.git
cd yumbox
# Create dev environment
python -m venv .venv
source .venv/bin/activate # or .venv\Scripts\activate on Windows
pip install -e ".[dev]" # Includes test/lint dependencies
# Make changes, add tests
pytest tests/ # Ensure nothing breaks
black yumbox/ # Format code
mypy yumbox/ # Type check
# Submit PR with description of changes
📝 Documentation
- Missing examples? Confusing API? PRs welcome!
- Include code snippets that actually run
📄 License
MIT — do whatever you want, just don't anyone if it breaks 😉
🙏 Acknowledgments
Yumbox stands on the shoulders of giants:
- FAISS for blazing-fast similarity search
- MLflow for experiment tracking done right
- hazm for Persian NLP
- parsel for robust HTML/XML parsing
- My university professors, work colleagues and friends, who helped shape this project.
🍱 Why "Yumbox"?
Because machine learning should be:
- Yummy: Enjoyable to use, satisfying results
- Modular: Mix and match components like ingredients
- Ready-to-eat: Minimal setup, maximum productivity
Now go build something delicious! 🚀
P.S. If you use Yumbox in your project, I'd love to hear about it. Tag me, star the repo, or just send a 🍱 emoji. I collect them.
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 yumbox-0.1.0.tar.gz.
File metadata
- Download URL: yumbox-0.1.0.tar.gz
- Upload date:
- Size: 143.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f943a4856a8f4e71cf4884097824617cf403d8fbb30288051fa3bd0116f7456a
|
|
| MD5 |
4f05598c285fec16f1f735d484cabd88
|
|
| BLAKE2b-256 |
8b4d549a4c9dbbc03252f70698e6da77a4f6515f12cbbead9ae3a110b28ce823
|
Provenance
The following attestation bundles were made for yumbox-0.1.0.tar.gz:
Publisher:
publish.yml on eshteharipour/yumbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
yumbox-0.1.0.tar.gz -
Subject digest:
f943a4856a8f4e71cf4884097824617cf403d8fbb30288051fa3bd0116f7456a - Sigstore transparency entry: 1613315341
- Sigstore integration time:
-
Permalink:
eshteharipour/yumbox@d99e75d5420a7672380a3e4f631002a7f325b9a8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/eshteharipour
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d99e75d5420a7672380a3e4f631002a7f325b9a8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file yumbox-0.1.0-py3-none-any.whl.
File metadata
- Download URL: yumbox-0.1.0-py3-none-any.whl
- Upload date:
- Size: 106.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d31cd681cb7238004b00fc4126615e4ee3a4e55e75098474a88ea82de565408a
|
|
| MD5 |
c9948cf8ab14b39d2e896144f91de9bf
|
|
| BLAKE2b-256 |
a93c21a923373831dcd28b2b1fca8fe3bb0f053eba3d7a4ae69a48892642ec9d
|
Provenance
The following attestation bundles were made for yumbox-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on eshteharipour/yumbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
yumbox-0.1.0-py3-none-any.whl -
Subject digest:
d31cd681cb7238004b00fc4126615e4ee3a4e55e75098474a88ea82de565408a - Sigstore transparency entry: 1613315444
- Sigstore integration time:
-
Permalink:
eshteharipour/yumbox@d99e75d5420a7672380a3e4f631002a7f325b9a8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/eshteharipour
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d99e75d5420a7672380a3e4f631002a7f325b9a8 -
Trigger Event:
push
-
Statement type: