odin-prompt-toolkit (Python)
Multi-language SDK for LSH (Locality-Sensitive Hashing) signature generation for AI prompt similarity detection.
This is the Python implementation of the odin-prompt-toolkit algorithm, also available in Rust and TypeScript.
Installation
0din-prompt-toolkit ships as two packages so you only ship compiled code when you want it:
| Package | What it is | When you get it |
|---|---|---|
0din-prompt-toolkit |
Pure-Python core. One universal (py3-none-any) wheel — installs on any OS/arch/Python, no compiler. |
Always (base install) |
0din-prompt-toolkit-native |
Optional Rust accelerator (PyO3). Prebuilt wheels for Linux/macOS/Windows × CPython 3.10–3.13. | Only with the [native] extra |
# Pure Python — works everywhere, slower signature generation
pip install 0din-prompt-toolkit
# With native Rust acceleration — recommended for production
pip install "0din-prompt-toolkit[native]"
# Optional features
pip install "0din-prompt-toolkit[onnx]" # local ONNX embeddings + SusFactor
pip install "0din-prompt-toolkit[openai]" # OpenAI embeddings
pip install "0din-prompt-toolkit[cm-lsh]" # Confidence Matrix LSH
pip install "0din-prompt-toolkit[threatfeed]" # 0DIN threat feed
pip install "0din-prompt-toolkit[all]" # everything, including native
From git (development):
pip install "0din-prompt-toolkit[native] @ git+https://github.com/0din-ai/prompt-toolkit#subdirectory=packages/python"
Native vs pure Python
Both paths produce bit-identical signatures (verified across all implementations via canonical test vectors). They differ only in how they install and how fast signature generation runs.
- Pure Python (
0din-prompt-toolkit) — a single universal wheel with no compiled code. Installs anywhere with zero build tools. Signature generation runs in a Python loop. - Native (
[native]→0din-prompt-toolkit-native) — a prebuilt compiled Rust extension.pipdownloads a wheel matching your platform, so no Rust toolchain or compiler is required on Linux/macOS/Windows with CPython 3.10–3.13. On any platform without a matching wheel, the base package still installs and automatically falls back to pure Python — nothing breaks, it's just slower.
The accelerator is transparent — the same API uses native automatically when it's present:
from odin_prompt_toolkit import NATIVE_AVAILABLE
print("native" if NATIVE_AVAILABLE else "pure Python")
Force pure Python even when native is installed: export ODIN_PROMPT_TOOLKIT_NO_NATIVE=1.
Speed tradeoff
Native replaces the hot signature-generation loop with compiled, SIMD-optimized Rust:
| Native (Rust) | Pure Python | |
|---|---|---|
| Throughput | ~5,300 sigs/sec | ~85 sigs/sec (384-dim) … ~9 sigs/sec (1024-dim) |
| Per signature | ~0.2 ms | ~12 ms … ~115 ms |
| vs native | — | ~60×–600× slower |
The multiplier depends on embedding dimension: pure Python loops over every dimension, so the gap widens with larger vectors (~63× at 384-dim, ~590× at 1024-dim). Native throughput is roughly constant.
What it means end-to-end: in a real pipeline, embedding generation usually dominates. On the 3,714-prompt benchmark (local ONNX, CPU) embedding took 112.6 s; adding signature generation cost 0.7 s with native (+0.6%) vs 43.8 s pure Python (+38%). When embeddings are pre-computed or cached (e.g. real-time dedup), signature generation is the cost — and the full speedup applies.
Rule of thumb: use [native] in production; pure Python is a correct, always-available fallback for prototyping or unusual platforms.
Quick Start
Basic LSH Signatures
from odin_prompt_toolkit import simhash_lsh_multi, normalize_vector
# Your embedding vector (must be L2-normalized)
vector = [0.5, 0.5, 0.5, 0.5]
normalized = normalize_vector(vector)
# Generate LSH signatures (3 families, 256 bits, 16 bands)
families = simhash_lsh_multi(normalized)
print(f"Signature: {families[0].signature}")
print(f"Bands: {families[0].bands}")
Similarity Comparison
from odin_prompt_toolkit import simhash_lsh_multi, hamming_distance_hex, cosine_from_hamming
# Generate signatures for two vectors
families1 = simhash_lsh_multi(vector1)
families2 = simhash_lsh_multi(vector2)
# Compute Hamming distance
distance = hamming_distance_hex(families1[0].signature, families2[0].signature)
# Estimate cosine similarity
similarity = cosine_from_hamming(distance, 256)
print(f"Estimated cosine similarity: {similarity:.3f}")
Confidence Matrix LSH (CM-LSH)
from odin_prompt_toolkit.cm_lsh import create_default_cm_lsh
# Create CM-LSH hasher (1024 dimensions)
cm_lsh = create_default_cm_lsh(1024, family=0)
# Generate 512-bit signature with confidence matrix
hash1 = cm_lsh.hash(embedding1)
hash2 = cm_lsh.hash(embedding2)
# Compute calibrated similarity
similarity = cm_lsh.sim(hash1, hash2)
print(f"CM-LSH similarity: {similarity:.3f}")
# Check for duplicates
is_duplicate = cm_lsh.is_dup(hash1, hash2, threshold=0.85)
Signature Versions
- V0: OpenAI text-embedding-3-large (1536 dimensions, API-based)
- V1: 0din-jailbreak-embeddings-small ONNX (1024 dimensions, local)
- Latest: Resolves to V1
Important: V0 and V1 signatures are not comparable due to different embedding spaces.
Algorithm
SimHash via Random Hyperplane LSH (Charikar 2002):
- Deterministic hyperplanes via SplitMix64 PRNG
- Default: 3 families × 256 bits × 16 bands
- Hex-encoded signatures (64 hex chars = 256 bits)
- Hamming distance → cosine similarity via
cos(π × d/n)
See the specification for complete algorithm details.
Development
Setup
cd python
pip install -e ".[dev]"
Run Tests
pytest tests/
Type Checking
mypy odin_prompt_toolkit/
Formatting
black odin_prompt_toolkit/ tests/
ruff check odin_prompt_toolkit/ tests/
License
Apache License 2.0
Metadata
Release files for 0din-prompt-toolkit 0.9.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| 0din_prompt_toolkit-0.9.5.tar.gz | 65.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 0din_prompt_toolkit-0.9.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 117.7 kB
Release files / 0din_prompt_toolkit-0.9.5.tar.gz
| Download URL | 0din_prompt_toolkit-0.9.5.tar.gz |
|---|---|
| Size | 65.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ebc041233fe918ca20504c39e6b2ef381fda852b0ff4c69ea396c2b53d63411e
|
|
BLAKE2b-256 checksum How to use checksums |
4f2305801f9ff82f402ad00bdb91600a450ab46341c1ec50f778bf9d3cde7eee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency logRelease files / 0din_prompt_toolkit-0.9.5-py3-none-any.whl
| Download URL | 0din_prompt_toolkit-0.9.5-py3-none-any.whl |
|---|---|
| Size | 52.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e949991187f88a2af76b2f662a88bb92a9073fc2d210fa5febc7e3a54bf4af2b
|
|
BLAKE2b-256 checksum How to use checksums |
7293be1d000f9924b251328c6c8bee17cdb744cdc52c69072506ce010a9b1fcd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency log