light-splade
light-splade provides a minimal yet extensible PyTorch implementation of SPLADE, a family of sparse neural retrievers that expand queries and documents into interpretable sparse representations.
Unlike dense retrievers, SPLADE produces sparse vectors in the vocabulary space, making it both efficient to index with standard IR engines (e.g., Lucene, Elasticsearch) and interpretable, while achieving strong retrieval effectiveness. It was first introduced in the paper “SPLADE: Sparse Lexical and Expansion Model for First Stage Ranking”.
This repository is designed for
- Practitioners wanting to
train SPLADE models on custom corpora. - Developers experimenting with
sparse lexical expansionat scale. - Researchers looking for a
reference implementation.
We currently support SPLADE v2 and SPLADE++
Features
- Training pipeline for SPLADE using PyTorch + HuggingFace Transformers.
- Support for
distillation trainingfrom dense retrievers (e.g., ColBERT, dense BERT). - Export trained models into sparse representations compatible with IR systems.
- Simple, lightweight, and easy to extend for experiments.
Installation
pip install light-splade
Quickstart
The following code uses bizreach-inc/light-splade-japanese-28M, an open SPLADE model for Japanese.
- Convert text to sparse vector with SPLADE model using this package
import torch
from light_splade import SpladeEncoder
# Initialize the encoder
encoder = SpladeEncoder(model_path="bizreach-inc/light-splade-japanese-28M")
# Tokenize input text
corpus = [
"日本の首都は東京です。",
"大阪万博は2025年に開催されます。"
]
# Generate sparse representation
with torch.inference_mode():
embeddings = encoder.encode(corpus)
sparse_vecs = encoder.to_sparse(embeddings)
print(sparse_vecs[0])
print(sparse_vecs[1])
- Convert text to sparse vector with SPLADE model using
transformerspackage
Install required packages
pip install fugashi torch transformers unidic-lite
Then execute the following Python code
import torch
from transformers import AutoTokenizer, AutoModelForMaskedLM
def dense_to_sparse(dense: torch.tensor, idx2token: dict[int, str]) -> list[dict[str, float]]:
rows, cols = dense.nonzero(as_tuple=True)
rows = rows.tolist()
cols = cols.tolist()
weights = dense[rows, cols].tolist()
sparse_vecs = [{} for _ in range(dense.size(0))]
for row, col, weight in zip(rows, cols, weights):
sparse_vecs[row][idx2token[col]] = round(weight, 2)
for i in range(len(sparse_vecs)):
sparse_vecs[i] = dict(sorted(sparse_vecs[i].items(), key=lambda x: x[1], reverse=True))
return sparse_vecs
MODEL_PATH = "bizreach-inc/light-splade-japanese-28M"
device = "cuda" if torch.cuda.is_available() else "cpu"
transformer = AutoModelForMaskedLM.from_pretrained(MODEL_PATH).to(device)
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
idx2token = {idx: token for token, idx in tokenizer.get_vocab().items()}
corpus = [
"日本の首都は東京です。",
"大阪万博は2025年に開催されます。"
]
token_outputs = tokenizer(corpus, padding=True, return_tensors="pt")
attention_mask = token_outputs["attention_mask"].to(device)
token_outputs = {key: value.to(device) for key, value in token_outputs.items()}
with torch.inference_mode():
outputs = transformer(**token_outputs)
# Compute in-place to reduce memory usage (safe here because no backward pass)
dense, _ = torch.max(
torch.relu_(outputs.logits).log1p_().mul_(attention_mask.unsqueeze(-1)),
dim=1,
)
sparse_vecs = dense_to_sparse(dense, idx2token)
print(sparse_vecs[0])
print(sparse_vecs[1])
- Output
{'首都': 1.83, '日本': 1.82, '東京': 1.78, '中立': 0.73, '都会': 0.69, '駒': 0.68, '州都': 0.67, '首相': 0.64, '足立': 0.62, 'です': 0.61, '都市': 0.54, 'ユニ': 0.54, '京都': 0.52, '国': 0.51, '発表': 0.49, '成田': 0.48, '太陽': 0.45, '藤原': 0.45, '私立': 0.42, '王国': 0.4...}
{'202': 1.61, '開催': 1.49, '大阪': 1.34, '万博': 1.19, '東京': 1.15, '年': 1.1, 'いつ': 1.05, '##5': 1.03, '203': 0.86, '月': 0.8, '期間': 0.79, '高槻': 0.79, '京都': 0.7, '神戸': 0.62, '2024': 0.54, '夢': 0.52, '206': 0.52, '姫路': 0.51, '行わ': 0.49, 'こう': 0.49, '芸術': 0.48...}
Setup for fine-tuning a SPLADE model
- Python 3.11+.
- Recommended: use the
uvtool to manage the virtual environment (see Getting started document).
Quick setup (recommended):
git clone https://github.com/bizreach-inc/light-splade.git
cd light-splade
# create and activate virtual env using uv
uv venv --seed .venv
source .venv/bin/activate
uv sync
For developer checks, run:
uv run pre-commit run --all-files
uv run pytest
Train SPLADE with toy dataset (triplet-based)
uv run examples/run_train_splade_triplet.py --config-name toy_splade_ja- To run on an environment without GPU, see this trouble shooting
For full run instructions using uv and Docker commands, see Getting started.
Input Data format
Detailed data format docs:
- Triplet format (
SPLADE v2) - Distillation format (
SPLADE++orSPLADE v2bis)
References
-
SPLADE v2: Sparse Lexical and Expansion Model for Information Retrieval. arxiv (SPLADE v2)
- Thibault Formal, Benjamin Piwowarski, Carlos Lassance, Stéphane Clinchant.
-
From Distillation to Hard Negative Sampling: Making Sparse Neural IR Models More Effective. SIGIR22 short paper (SPLADE++ or SPLADE v2bis)
- Thibault Formal, Carlos Lassance, Benjamin Piwowarski, Stéphane Clinchant.
-
For
transformersdocs:
License
This project is licensed under the Apache License, Version 2.0 — see the LICENSE file for details.
Copyright 2025 BizReach, Inc.
Metadata
Release files for light-splade 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| light_splade-0.1.3.tar.gz | 224.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| light_splade-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 305.3 kB
Release files / light_splade-0.1.3.tar.gz
| Download URL | light_splade-0.1.3.tar.gz |
|---|---|
| Size | 224.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d0dac64a6c93fd38654d860dc523346b5102229ce6685972005556d7d87fae6d
|
|
BLAKE2b-256 checksum How to use checksums |
565884652d320b1a0c729ab97c506f48e5e3aecd7bbaf890684ce5946ea77bc6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / light_splade-0.1.3-py3-none-any.whl
| Download URL | light_splade-0.1.3-py3-none-any.whl |
|---|---|
| Size | 80.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
65f49f93033989cdb62fb9c3db5f02116076d151f2247019d129464136f5ab45
|
|
BLAKE2b-256 checksum How to use checksums |
9caf8583daddf2bfe407699ac1bebf3cf4a2daab3f600adcb97b698885765cca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|