Skip to main content

zuhut-align

Cross-model embedding alignment. Bridge any two embedding models — zero-shot, no labels, no reindexing.

PyPI License


The Problem

You have millions of documents indexed with bge-large-en-v1.5 (1024d).
You want to query with MiniLM (384d) — faster, cheaper, fits on edge.

Without alignment: R@5 = 0.13 (unusable).
With ZUHUT: R@5 = 0.70 (91% of same-model ceiling) — zero reindexing.


Install

# Level 1 — ZeroShot (free, no GPU needed)
pip install zuhut-align

# Level 2 — PhaseMLP training (requires PyTorch)
pip install 'zuhut-align[mlp]'

# Full install
pip install 'zuhut-align[full]'

Quick Start

Level 1 — ZeroShot (Free)

from zuhut_align import ZUHUTClient

# No API key needed
client = ZUHUTClient()
adapter = client.create_adapter(src_dim=1024)   # bge-large → MiniLM space

# Align your corpus vectors once (store the result in Qdrant/FAISS/etc.)
corpus_aligned = adapter.transform(corpus_vectors_1024d)   # shape (N, 384)

# Align query at search time
query_aligned = adapter.transform(query_vector_1024d)      # shape (1, 384)

# Now search corpus_aligned with query_aligned using cosine similarity

Result: R@5 jumps from 0.13 → 0.40. Zero training. Zero data. Instant.


Level 2 — PhaseMLP (Paid, ~5 min training)

from zuhut_align import ZUHUTClient
from sentence_transformers import SentenceTransformer

model_b = SentenceTransformer("paraphrase-MiniLM-L6-v2")

client  = ZUHUTClient(api_key="zuhut-your-key-here")
trainer = client.create_adapter(src_dim=1024, tier="phasemlp")

# Train on 200–500 sample docs from your corpus (NOT the full corpus)
# Training time: ~5 min on CPU regardless of corpus size
trainer.train(
    corpus_texts=sample_docs,     # List[str], 200–500 docs
    embedder=model_b.encode,      # Your query-side encoder
)

# Now trainer is a PhaseMLP_Trainer with a trained .mlp
adapter = trainer   # .transform() is available after training

corpus_aligned = adapter.transform(corpus_vectors_1024d)
query_aligned  = adapter.transform(query_vector_1024d)

Result: R@5 = 0.70 — 91% of same-model ceiling.


Full Qdrant Example

from zuhut_align import ZUHUTClient
from sentence_transformers import SentenceTransformer
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct

# 1. Models
model_a = SentenceTransformer("BAAI/bge-large-en-v1.5")    # corpus model
model_b = SentenceTransformer("paraphrase-MiniLM-L6-v2")   # query model

# 2. ZUHUT alignment (zero-shot)
client  = ZUHUTClient()
adapter = client.create_adapter(src_dim=1024)

# 3. Encode & align corpus
corpus_vecs   = model_a.encode(corpus_docs, normalize_embeddings=True)
corpus_zuhut  = adapter.transform(corpus_vecs)   # shape (N, 384)

# 4. Index into Qdrant (384d, one-time)
qdrant = QdrantClient(host="localhost", port=6333)
qdrant.recreate_collection("my_corpus", vectors_config=VectorParams(
    size=384, distance=Distance.COSINE
))
qdrant.upsert("my_corpus", points=[
    PointStruct(id=i, vector=corpus_zuhut[i].tolist())
    for i in range(len(corpus_docs))
])

# 5. Search with cheap query model
query    = "how do neural networks learn?"
q_vec    = model_b.encode(query, normalize_embeddings=True)
q_zuhut  = adapter.transform(q_vec)

results  = qdrant.query_points("my_corpus", query=q_zuhut[0].tolist(), limit=5)

How It Works

Source Model (1024d)
       ↓
   SVD Projection → 384d
       ↓
 Procrustes Rotation  ← synthetic anchors (N=250, SEED=42)
       ↓
  L2 Normalize
       ↓
  [PhaseMLP] ← optional, trained on your corpus pseudo-pairs
       ↓
Target Space (384d) — compatible with your indexed corpus

Zero-Shot (Level 1)

  • Generates 250 synthetic Gaussian anchor pairs
  • Learns an SVD projection (dim reduction) + Procrustes rotation
  • No real data, no training, reproducible across runs

PhaseMLP (Level 2)

  • Residual MLP (x + net(x)) with zero-init last layer
  • Trained with InfoNCE contrastive loss on corpus pseudo-pairs
  • Pseudo-pairs via word dropout (10% random word removal)
  • Training invariant to corpus size: 200–500 docs → 5 min on CPU

Benchmark Results

Tested on Qdrant with BGE-large (corpus) vs MiniLM (query):

Condition R@5 vs Ceiling
Same-model baseline (ceiling) 0.767 —
Cross-model, no alignment 0.133 -63.3%
+ ZUHUT ZeroShot (Level 1) 0.400 -36.7%
+ ZUHUT PhaseMLP v3 (Level 2) 0.700 -6.7%

Vector databases tested: Qdrant ✓, FAISS ✓, LanceDB ✓, ChromaDB ✓


Tiers

Level 1 ZeroShot Level 2 PhaseMLP Level 3 Engine
Price Free Paid Enterprise
Training data None 200–500 docs None
Training time 0s ~5 min CPU 0s
R@5 gain +30% +57% +57%
Inference speed Fast (NumPy) Fast (PyTorch) Ultra (Rust)
API key Not required Required License key

Requirements

  • Python ≥ 3.9
  • numpy ≥ 1.24
  • scipy ≥ 1.10
  • torch ≥ 2.0 (Level 2 only)
  • sentence-transformers ≥ 2.7 (Level 2 only)

License

Apache 2.0 — Python SDK is open source.
The Rust engine (zuhri_engine) is proprietary (Level 3 / Enterprise).


Metadata

Release files for zuhut-align 0.1.2

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

Source distribution (sdist)

Source distribution for zuhut-align 0.1.2
File Size Uploaded Provenance Actions
zuhut_align-0.1.2.tar.gz 15.2 kB Without provenance Details for zuhut_align-0.1.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for zuhut-align 0.1.2
File Interpreter ABI Platform Actions
zuhut_align-0.1.2-py3-none-any.whl Python 3 none any Details for zuhut_align-0.1.2-py3-none-any.whl

Total release size: 29.9 kB

Release files / zuhut_align-0.1.2.tar.gz

Download URL zuhut_align-0.1.2.tar.gz
Size 15.2 kB
Tags Source
SHA-256 checksum
How to use checksums
6c32df846994acaf3a68ad6f4f386e60fcdfd6ee00f8557d1f9ca5cbcad6f54a
BLAKE2b-256 checksum
How to use checksums
92f2e7fe696e93f1684b7df158011b6eb4770ca92ce46e949e552dea72ac432e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.13

Release files / zuhut_align-0.1.2-py3-none-any.whl

Download URL zuhut_align-0.1.2-py3-none-any.whl
Size 14.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dc0b6ae2f95eb6651c385eda5c0c92bbb8aa02037b22928a8165dc351a3401fb
BLAKE2b-256 checksum
How to use checksums
32e4fc14c6044915719ee9fcd6c2d3fd0dd644d2e8fb4fb015dd2af795bedd59
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.13

Security for zuhut-align 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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