Latent Scope turns embedding, projection, clustering and labelling into one annotated map
A scientific instrument for investigating latent spaces
At a glance
- What is it?
- Latent Scope is a Python and web application that embeds unstructured data, projects it with UMAP, clusters it, labels the clusters with an LLM and lets you explore the result in a browser linked back to the source rows. It is at version 1.0, works with text and images, and deliberately leaves curation for a later release.
- Who is it for?
- Latent Scope fits a data scientist or researcher who has a large pile of unstructured text or images and wants to find structure in it, and who wants the clustering labelled by a model rather than left as umap-001 through umap-120.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 64 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The five step pipeline the tool is built around
The README describes Latent Scope as encoding a process that is increasingly common in AI and data science workflows: embed unstructured data into high-dimensional vectors, reduce the dimensionality of those vectors, cluster the resulting points, label the clusters with an LLM and then explore the annotated data.
That sequence is the product. A separate web interface for each step is described as making the process easier, and the exploration step is described as an intuitive way to explore the resulting annotated data via an interactive visualization tightly coupled with the input data.
The framing is worth comparing with the way this is usually done by hand. The usual pipeline is a notebook: load a CSV, call an embedding API, fit UMAP, run HDBSCAN, print some cluster sizes, write a script that asks a model to name each cluster, and hope the labels are right. Every step is a separate artefact and the intermediate state lives in files you have to keep track of.
Latent Scope makes it a scope. The demo links at latent.estate show what that means concretely: a Fineweb EDU sample, a dad jokes dataset, the Common Corpus and a Data is Plural collection, each rendered as a set of scope views. A scope is a named, self-contained experiment with its data, its projection, its clusters and its labels.
The named experiments feature says the same thing in the interface: you can give UMAP and cluster runs human-friendly names and descriptions and browse them as a thumbnail gallery instead of a bare umap-001 id list.
What you can point it at, and which provider computes the embedding
Latent Scope works with text and image datasets, and the provider list is wide.
For dense embeddings the options are sentence-transformers and HuggingFace models, OpenAI, Cohere, Voyage, Mistral, Together, and any OpenAI-compatible endpoint. That last one matters more than it sounds, because it means a self-hosted or local model with an OpenAI-shaped API can be used without code changes.
Beyond dense vectors there are two specialised paths. ColBERT late-interaction, multi-vector embeddings are supported with MaxSim similarity search, with a quickstart in examples/colbert_quickstart/. Image embeddings in the CLIP style are supported, and they come with an interactive image map: a zoomable representative-image sprite atlas that takes over from the heatmap as you zoom in. That detail is the interesting part, because a heatmap tells you a region is dense and a sprite atlas tells you what the region contains.
The storage and projection layer is LanceDB for vector storage, UMAP for the projection, and an LLM for the cluster labelling.
Clustering is where the tool offers genuine choice rather than one default. There are four methods, EVoC, HDBSCAN, KMeans and Gaussian Mixture, and you can cluster on the 2D UMAP or on the high-dimensional embedding, chosen with the ls-cluster --method option and documented in docs/clustering.md.
That choice is not cosmetic. HDBSCAN on a 2D projection finds visually distinct blobs and ignores everything else. KMeans forces every point into one of k clusters whether or not the data has that structure. Clustering the high-dimensional embedding instead of the projection can give different and arguably more faithful clusters, at a cost in interpretability of the map.
Running it locally, and where the data lives
The quick start is short, and the project is a local server rather than a hosted service.
Latent Scope works on Mac, Linux and Windows, with Python 3.12 recommended, and the package is on PyPI as latentscope. The install sequence is a virtual environment and pip install.
python -m venv venv
source venv/bin/activate
pip install latentscopeThe environment variables come from a .env file, and the repository ships an example to copy. The example shows the shape of the configuration, with one key per provider and the local data directory.
OPENAI_API_KEY=XXX
OPENAI_BASE_URL=XXX # optional, defaults to https://api.openai.com
VOYAGE_API_KEY=XXX
TOGETHER_API_KEY=XXX
COHERE_API_KEY=XXX
MISTRAL_API_KEY=XXX
LATENT_SCOPE_DATA='~/latent-scope-data'The keys are all optional in the sense that you only need the ones for the providers you actually use, and OPENAI_BASE_URL being overridable is what lets you point at any OpenAI-compatible endpoint.
The data directory is the other thing to understand. LATENT_SCOPE_DATA points at a local directory, and the init step creates a scope there. Everything the tool computes, the embeddings, the projection, the cluster assignments, the labels, lives on your disk. There is no upload, and there is no shared state between scopes.
That is the privacy property of the design and also its limitation. Two people cannot look at the same scope unless they share the directory, and there is no authentication layer described anywhere in the documentation for the web interface.
GPU acceleration is opt-in and falls back automatically
The performance feature is described precisely enough to be useful.
GPU acceleration is optional: cuML-accelerated UMAP, HDBSCAN and KMeans on NVIDIA GPUs, with automatic CPU fallback. It is controlled by an environment variable, LATENT_SCOPE_DEVICE, and documented in docs/gpu-acceleration.md.
The automatic fallback is the part that matters. In a pipeline that switches between a workstation with a GPU and a laptop without one, an explicit device setting that fails hard would break the run, whereas a fallback means the same command works on both. The cost is that you do not always know which path ran, which is worth knowing if you are comparing timings.
Note what is accelerated. UMAP, HDBSCAN and KMeans are named. The dense embedding step is not, because that runs in the provider's infrastructure or in a local model, not in this process. So the acceleration applies to the middle of the pipeline, where the projection and the clustering happen, and it does not remove the cost of embedding your dataset.
The dependency list explains the shape of the install. torch, transformers and sentence-transformers for local models, umap-learn and hdbscan for the projection and clustering, evoc for the fourth clustering method, latentsae and datamapplot for the visualisation, scikit-learn, scipy, numpy and pandas, and lancedb with pylance for storage. The pyproject.toml pins lancedb and pylance to a tested pair and explains why in a comment: fresh resolves of lancedb 0.33 with pylance 0.39 break, because LanceDataset lost to_pandas.
That comment is worth reading before you widen the pins yourself. The upper bounds are a gate, not an oversight, and the README says as much with the test suite as the gate.
Curation is the missing half, and the project says so
There is one conspicuous absence, and the README highlights it rather than hiding it.
Curation, meaning deleting rows, tagging during Setup, and reassigning clusters, is not part of 1.0. It is planned as a post-1.0, 1.1 initiative, and the README points at docs/exploring.md for the section explaining it.
That is a significant boundary for anyone evaluating the tool for real work. The pipeline as shipped goes from raw data to a labelled map, and the labels are the LLM's names for the clusters. If you need to correct a bad label, merge two clusters that the clustering split for no good reason, or remove the rows that landed in a garbage cluster, none of that is in 1.0. You would be doing it in your own code, against the exported data.
The rest of the exploration features are present, and they are the ones that make the map useful for reading rather than editing. Color-by and Compare let you color the Explore and Compare maps by any numeric or categorical column, and you can share a lasso or brush selection across both Compare panes.
The Compare feature is worth singling out. Most dimensionality reduction tools give you one projection, and comparing two datasets means running the tool twice and mentally aligning two pictures. A Compare view with a linked selection is a way to ask a comparative question directly, and it is the feature that would matter most to anyone using this on two corpora.
The image map for image embeddings is the other visual feature, and it sits on the same principle: a heatmap tells you a region is dense, a sprite atlas tells you what the region contains.
Where Latent Scope is the wrong tool
The first limitation is that there is no hosted, shared version described. This is a local server with a local data directory, a local environment file and a browser tab on your own machine. For a team that wants to share a scope with colleagues, there is no documented multi-user or authentication story, and the shared selection in Compare panes is a browser feature rather than a collaboration feature.
The second is the dependency on a labelling model working well. The whole point of the pipeline is to have an LLM name the clusters, and that step can be wrong in ways that are hard to detect, because a plausible name on a nonsense cluster looks fine on screen. Without curation in 1.0, there is no correction loop, so the quality of the labels depends on the quality of the model and on how homogeneous the clusters are.
The third is scale. There is a data-size guidance document mentioned in the README, docs/data-importing.md, but no claim about how much data this handles. UMAP on a very large embedding set is slow and memory hungry, and with GPU acceleration being optional, an evaluation on a laptop will be slower than on the machine you would deploy on.
The fourth is that the package is heavy. torch, transformers, sentence-transformers, umap-learn, hdbscan, evoc, latentsae, scikit-learn, scipy, numpy, pandas, lancedb and the provider SDKs is a large install for an exploration tool, and the pyproject.toml shows deliberate upper bounds on several of them.
The fifth is the release cadence. Version 1.0.0 landed on 2026-07-12, with 0.6.0 in February 2025 and 0.5.1 named SAE Features in December 2024, and the last push was on 2026-08-21. The 1.0 label is recent and the 1.1 curation work is on the roadmap but not scheduled.
How it compares to a notebook and to a hosted embedding explorer
The two alternatives are a notebook you write yourself, and a hosted product for exploring embeddings.
The notebook is what most people already do, and its strength is that it is code you own. Every step is explicit, the intermediate arrays are in memory, and you can add a step the tool does not have. Its weakness is the one this project targets: the state is scattered across a .npy file, a UMAP embedding, a labels file and a dataframe, and the mapping between them is implicit. That is exactly the bookkeeping Latent Scope makes automatic, and the value scales with the number of experiments you run rather than with the sophistication of any single one.
The hosted explorer is the other direction. Services that let you upload a dataset and browse its embedding space do the same thing with no install and no model keys, but they are a web service with a web service's constraints: your data goes somewhere, the model is theirs, and the parameterisation is limited to what the product exposes.
Latent Scope sits in between and its own README is explicit about the trade. It works with open models locally or via API, which is the phrase that captures it. You can use a local sentence-transformers model and never send a row anywhere, or point at an API provider and only your embeddings leave the machine.
The most distinctive feature is the agent skill. Latent Scope ships a cross-provider agent skill so Claude Code, Codex and Cursor can drive the pipeline on your behalf, with the runbook in AGENTS.md, which Claude Code auto-loads from .claude/skills/latent-scope/. Point the agent at the repository and ask it to map my data and it is supposed to know the whole flow. That is a different adoption model from a GUI, and for a team that already works through coding agents it is arguably the primary interface.
Editorial conclusion
Latent Scope fits a data scientist or researcher who has a large pile of unstructured text or images and wants to find structure in it, and who wants the clustering labelled by a model rather than left as umap-001 through umap-120. It does not fit a pipeline that needs to edit the data, because curation is explicitly not part of 1.0 and is planned for 1.1, and it does not fit a team that needs a hosted multi-user service, since it is a local server with a local data directory. Before you start, read docs/data-importing.md for the input formats and the data size guidance, choose a clustering method deliberately because the choice changes what the labels mean, and set the provider keys in a .env file copied from .env.example rather than on the command line.
Frequently asked questions
What is Latent Scope and what pipeline does it run?
It is a Python and web tool that embeds unstructured data into high-dimensional vectors, reduces the dimensionality with UMAP, clusters the points, labels the clusters with an LLM and then lets you explore the annotated data in an interactive visualisation coupled to the input rows.
How do I install and set up Latent Scope?
Create a virtual environment, activate it and run pip install latentscope, then set the provider keys and the data directory in a .env file copied from the repository's .env.example. The keys shown there are OPENAI_API_KEY, VOYAGE_API_KEY, TOGETHER_API_KEY, COHERE_API_KEY and MISTRAL_API_KEY, plus LATENT_SCOPE_DATA for the local data directory. Python 3.12 is the recommended version.
Which clustering methods does Latent Scope support?
EVoC, HDBSCAN, KMeans and Gaussian Mixture, selected with ls-cluster --method, and you can cluster on the 2D UMAP or on the high-dimensional embedding. The details are in docs/clustering.md.
Can Latent Scope edit or curate the data?
Not in 1.0. The README states that curation, meaning deleting rows, tagging during Setup and reassigning clusters, is not part of 1.0 and is planned as a post-1.0, 1.1 initiative, with the details in docs/exploring.md.
Does Latent Scope need a GPU?
No, GPU acceleration is optional. cuML-accelerated UMAP, HDBSCAN and KMeans run on NVIDIA GPUs with automatic CPU fallback, controlled by the LATENT_SCOPE_DEVICE environment variable and described in docs/gpu-acceleration.md.
What embedding providers does Latent Scope support?
Dense embeddings from sentence-transformers and HuggingFace, OpenAI, Cohere, Voyage, Mistral, Together and any OpenAI-compatible endpoint, plus ColBERT late-interaction multi-vector embeddings with MaxSim similarity and CLIP-style image embeddings with an interactive image map.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/enjalot-latent-scope)Was this useful?