embedding-dedupe
Deduplicate near-identical embedding records by cosine similarity. Pure Python, zero runtime dependencies.
Python port of @mukundakatta/embedding-dedupe. Same algorithm, ergonomic Python API.
Install
pip install embedding-dedupe
# Optional: faster cosine via numpy
pip install "embedding-dedupe[numpy]"
Usage
from embedding_dedupe import dedupe
records = [
{"id": "a", "embedding": [0.10, 0.20, 0.30], "text": "Cats are great."},
{"id": "b", "embedding": [0.10, 0.20, 0.31], "text": "Cats are great pets."}, # near-dup of a
{"id": "c", "embedding": [0.90, 0.10, 0.05], "text": "Stock prices fell."},
]
# Default: keep the lowest-id record from each cluster (deterministic).
dedupe(records, threshold=0.95)
# -> [
# {"id": "a", "embedding": [0.10, 0.20, 0.30], "text": "Cats are great."},
# {"id": "c", "embedding": [0.90, 0.10, 0.05], "text": "Stock prices fell."},
# ]
# Or: keep the record with the longest text (ties -> lowest id).
dedupe(records, threshold=0.95, keep="longest")
# -> [
# {"id": "b", "embedding": [0.10, 0.20, 0.31], "text": "Cats are great pets."},
# {"id": "c", "embedding": [0.90, 0.10, 0.05], "text": "Stock prices fell."},
# ]
API
dedupe(
records, # list[dict]
threshold=0.95, # cosine sim above which two records are duplicates
key="id", # record id field name
vector="embedding", # embedding field name
keep="first", # "first" (lowest-id) or "longest" (longest .text)
) -> list[dict]
cosine(a, b) is also exported for ad-hoc use.
Algorithm
Greedy single-link clustering: scan records in input order, place each into the first existing cluster whose anchor vector is within threshold, else start a new cluster. From each cluster, return one survivor according to keep. Cluster output order matches input order (= order in which clusters were created).
O(n * k) where k is the cluster count -- fine up to ~100k records. For larger sets, plug in an ANN index upstream and dedupe within candidates.
API differences from the JS sibling
- JS:
dedupeEmbeddings(items, { threshold })returning{ kept, duplicates }. Python:dedupe(records, threshold=0.95, key=, vector=, keep=)returning a flatlist[dict]of survivors. - The default threshold is
0.95(was0.98in JS) -- tuned for typical OpenAI/Anthropic embedding noise. - New
keep="longest"strategy mirrors a common request -- prefer the most informative chunk in each cluster.
See the JS sibling for the original heuristics and design notes.
Metadata
Release files for embedding-dedupe 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| embedding_dedupe-0.1.0.tar.gz | 5.7 kB | Without provenance | Details for embedding_dedupe-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| embedding_dedupe-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for embedding_dedupe-0.1.0-py3-none-any.whl |
Total release size: 11.3 kB
Release files / embedding_dedupe-0.1.0.tar.gz
| Download URL | embedding_dedupe-0.1.0.tar.gz |
|---|---|
| Size | 5.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d8525a9d2bd3a48386f5993ed2c5d034ea731432b53234a77531906d0ab4a249
|
|
BLAKE2b-256 checksum How to use checksums |
2e28adf7b7c4ebc1416aadc2ad1ed14511cb1f7edb90d9bdd53d8ab1ee6eafff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|
Release files / embedding_dedupe-0.1.0-py3-none-any.whl
| Download URL | embedding_dedupe-0.1.0-py3-none-any.whl |
|---|---|
| Size | 5.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
24cab99651b23ae5df617292cea0efc806cfd46472513a9bd759d2df0ffb14f1
|
|
BLAKE2b-256 checksum How to use checksums |
0039c1b84676ee70f9498aea7d56d0a328990680c3fc0228b0f7ec561906af3f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|
Security for embedding-dedupe 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.