Skip to main content

Semantic text clustering using sentence embeddings and agglomerative clustering.

Project description

semaclust

CI PyPI version Python versions License: MIT

semaclust (semantic + clustering) is a small Python library for clustering similar strings using sentence embeddings and agglomerative clustering. It is useful for deduplicating free-text fields, normalizing user-entered values, and collapsing spelling or formatting variants into a canonical form.

Installation

pip install semaclust
# or
uv add semaclust

Install from source:

pip install git+https://github.com/cobanov/semaclust.git

Quickstart

from semaclust import TextClusterer

texts = [
    "New York", "NYC", "new york city",
    "Los Angeles", "LA",
    "San Francisco", "San Fran", "SF",
]

clusterer = TextClusterer(distance_threshold=0.5)
clusterer.fit(texts)

print(clusterer.n_clusters_)
# 3

print(clusterer.clusters_)
# {0: ['New York', 'NYC', 'new york city'],
#  1: ['Los Angeles', 'LA'],
#  2: ['San Francisco', 'San Fran', 'SF']}

print(clusterer.transform())
# ['NYC', 'NYC', 'NYC', 'LA', 'LA', 'SF', 'SF', 'SF']

fit_transform is the one-call shortcut:

TextClusterer(distance_threshold=0.5).fit_transform(texts)

API at a glance

Method Returns Purpose
fit(texts) self Cluster and store fitted attributes
fit_predict(texts) ndarray[int] Cluster labels per input text
fit_transform(texts) list[str] Each text replaced with its representative
transform(texts=None) list[str] Replace texts seen at fit time
get_replacement_map() dict[str, str] Mapping from original to representative
result_ ClusterResult Frozen dataclass with labels, clusters, reps

Fitted attributes (sklearn convention): labels_, clusters_, representatives_, n_clusters_, texts_.

Plugging in your own encoder

Any object implementing encode(texts: list[str]) -> np.ndarray satisfies the Encoder protocol:

from semaclust import TextClusterer, Encoder
import numpy as np

class MyEncoder:
    def encode(self, texts: list[str]) -> np.ndarray:
        return np.random.rand(len(texts), 384).astype(np.float32)

clusterer = TextClusterer(encoder=MyEncoder())

CLI

semaclust ships a small typer-based CLI:

# Cluster lines from a file, write JSON
semaclust cluster items.txt --threshold 0.4 --output clusters.json

# Replace each line with its cluster representative
cat items.txt | semaclust replace --threshold 0.4

Run semaclust --help for the full reference.

Migration from 0.1.x

The 0.3 release is a breaking change. The single cluster(texts) entry point is gone; the new API mirrors scikit-learn:

0.1.x 0.3.x
clusterer.cluster(texts) clusterer.fit(texts).clusters_
clusterer.get_replacement_map(texts) clusterer.fit(texts).get_replacement_map()
clusterer.replace_values(texts) clusterer.fit_transform(texts)

The representative_selector argument moved from per-call to the constructor.

Development

git clone https://github.com/cobanov/semaclust.git
cd semaclust
uv sync --extra dev
uv run pytest
uv run ruff check src tests
uv run mypy src/semaclust

Install the pre-commit hooks once:

uv run pre-commit install

License

MIT, see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

semaclust-0.3.0.tar.gz (13.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

semaclust-0.3.0-py3-none-any.whl (10.5 kB view details)

Uploaded Python 3

File details

Details for the file semaclust-0.3.0.tar.gz.

File metadata

  • Download URL: semaclust-0.3.0.tar.gz
  • Upload date:
  • Size: 13.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for semaclust-0.3.0.tar.gz
Algorithm Hash digest
SHA256 5f997888058b0b3071c7f656775a269e320ab9c64ff2eb73aaff31c57c0db2f9
MD5 1738aae1e4d75025e1538dc7fda4ca12
BLAKE2b-256 f89d7cca6f6f8daf8d5de3111ad0f1f03a5fc5d3a63abaab7b19a6e2cb64726d

See more details on using hashes here.

Provenance

The following attestation bundles were made for semaclust-0.3.0.tar.gz:

Publisher: release.yml on cobanov/semaclust

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file semaclust-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: semaclust-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 10.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for semaclust-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a46b0a970929c5c2d01b367c49cf66502de9fdbd5eced0f41a4a5d37c1f1e5fd
MD5 28964aeee0cdc86e7e8c8f56c021dfe6
BLAKE2b-256 182a60cc3fb85989433b7a94d6c541c1e9a8cc3418a3360a2abe8ae49c7f9eaf

See more details on using hashes here.

Provenance

The following attestation bundles were made for semaclust-0.3.0-py3-none-any.whl:

Publisher: release.yml on cobanov/semaclust

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page