jev-reranking / README.md
rdxtremity's picture
Query-side encoders: bge-m3 LoRA adapter, tokenizer, SPLADE
cae796e verified
|
Raw History Blame Contribute Delete
1.96 kB
---
license: apache-2.0
language:
- en
- ar
tags:
- retrieval
- search
- sparse-encoder
- splade
- bge-m3
- lora
library_name: peft
---
# Search Stack — query towers
The **query-side** encoders for a two-stage product search over a multilingual
(EN + AR) fashion catalogue. These are the exact weights that produced the
vectors in the Qdrant collection they are used against — a cosine ANN is only
meaningful if query and documents share an encoder, so these are part of the
retrieval contract, not an interchangeable dependency.
| path | size | what it is |
|---|---|---|
| `adapter/` | 4.7 MB | LoRA (r=8, q/k/v) on `BAAI/bge-m3` — the dense query tower |
| `tokenizer/` | 17 MB | matching bge-m3 tokenizer |
| `splade_v6_v2/` | 545 MB | fine-tuned SPLADE sparse encoder (distilbert-base-multilingual-cased) |
The `BAAI/bge-m3` backbone is not included — it is unmodified upstream and
`transformers` fetches it on first run.
## Use
```python
from huggingface_hub import snapshot_download
snapshot_download("rdxtremity/jev-reranking",
allow_patterns=["adapter/*", "tokenizer/*", "splade_v6_v2/*"],
local_dir="models")
```
Dense query encoding is CLS-pool + L2-normalise, max 64 tokens, producing a
1024-d unit vector:
```python
from transformers import AutoModel, AutoTokenizer
from peft import PeftModel
import torch
tok = AutoTokenizer.from_pretrained("models/tokenizer")
model = PeftModel.from_pretrained(AutoModel.from_pretrained("BAAI/bge-m3"),
"models/adapter").eval()
enc = tok(["red dress"], return_tensors="pt", truncation=True, max_length=64)
with torch.no_grad():
out = model(**enc)
vec = torch.nn.functional.normalize(out.last_hidden_state[:, 0], p=2, dim=-1)
```
Sparse encoding uses `sentence_transformers.SparseEncoder` on `splade_v6_v2/`,
with `max_seq_length = 128`.
Only one short forward pass runs at query time, so CPU is sufficient.