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.0

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.0
File Size Uploaded Provenance Actions
zuhut_align-0.1.0.tar.gz 15.0 kB Without provenance Details for zuhut_align-0.1.0.tar.gz

Built distribution (wheel)

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

Total release size: 29.7 kB

Release files / zuhut_align-0.1.0.tar.gz

Download URL zuhut_align-0.1.0.tar.gz
Size 15.0 kB
Tags Source
SHA-256 checksum
How to use checksums
41d1908b70a70bb7b24d66170fe232cf63603e9bf8effef8ec44d48deb3428ab
BLAKE2b-256 checksum
How to use checksums
499ae26c0f10a544aa7b771435cf38c38aca0c97327f5a16c81e6ce50cc28d03
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.0-py3-none-any.whl

Download URL zuhut_align-0.1.0-py3-none-any.whl
Size 14.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2bfb9e37d0a46a3279282e1eb7426429220da27a66d5ad8834158df59416194d
BLAKE2b-256 checksum
How to use checksums
b0b301bd6a41a2021b47fb6a78c0ac6203f08e821cf6a0fe640fda143acbb007
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.0

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