MeaningFlow: Finding What Your Content Is Missing

An open-source framework for semantic coverage gap analysis.
Every content team I’ve worked with has the same problem. They know what they’ve published. They have some idea of what their users are searching for. But they can’t see the gap between the two — at least not at scale, and not in a way that’s grounded in how language actually works rather than keyword spreadsheets.
That’s the problem MeaningFlow solves.
What It Does
MeaningFlow takes two inputs: a set of user queries (what people want) and a set of content titles or pages (what you already have). It embeds both into a shared semantic space using Sentence-BERT, clusters them by topic using HDBSCAN, builds a graph of how those topics relate to each other, and then computes the gap — demand clusters with no corresponding supply.
The output is a ranked list of content opportunities: topics where your audience has real demand and your site has nothing.
from meaningflow import SemanticGraph
demand = SemanticGraph(texts=queries, volumes=search_volumes, embedder="all-MiniLM-L6-v2")
demand.fit()
supply = SemanticGraph(texts=content, embedder="all-MiniLM-L6-v2")
supply.fit()
gaps = demand.coverage_gaps(reference=supply, similarity_threshold=0.55)
for gap in gaps[:10]:
print(f"{gap.top_terms[:3]} volume={gap.volume} size={gap.size}")That’s the core workflow. Six lines from raw text to a prioritized gap list.
Why Embeddings Instead of Keywords
Traditional content gap analysis compares keyword lists. You pull your ranking keywords from one tool, your competitors’ keywords from another, diff them, and get a list of keywords you’re “missing.”
The problem is that keywords are surface-level. “How to train a puppy” and “puppy training tips” are different keyword strings that mean the same thing. “Apple” is one keyword that means three different things. Keyword-level gap analysis either misses synonymous demand or conflates unrelated demand.
MeaningFlow operates in embedding space, where meaning is the unit of analysis. Texts that mean the same thing land near each other regardless of the words they use. Texts that happen to share words but mean different things land far apart. The clusters that emerge represent genuine topics — not strings.
This is the difference between “you’re missing the keyword ‘gecko care’” and “you have an entire topical area around reptile husbandry with 2,000 monthly queries and zero content.”
What’s in v0.2
The release includes:
SemanticGraph — the main entry point. Wraps the full embed, reduce, cluster, graph pipeline into a single .fit() call. Properties include .clusters, .n_clusters, .noise_ratio, and the underlying .graph (NetworkX).
Coverage gap analysis — .coverage_gaps() compares a demand graph against a supply graph and returns GapCluster objects sorted by volume. Each gap includes the top representative terms, total search volume, and the nearest supply cluster with its similarity score.
Neo4j export — write your semantic graph directly to a Neo4j database, or export as a Cypher script. Each cluster becomes a node, each inter-cluster relationship becomes an edge. Useful for visualization, for integrating with existing knowledge graphs, or for feeding into a GraphRAG pipeline.
Demo notebook — a self-contained Jupyter notebook with embedded sample data (a pet supplies scenario) that walks through the full pipeline from raw text to a gap report with visualization.
Use Cases Beyond Content Gaps
The framework was built for content teams, but the same pipeline applies anywhere you need to compare two corpora and find structural differences:
Taxonomy design. Run MeaningFlow on your query logs. The clusters are a data-driven starting point for your category hierarchy. Editors name the clusters and decide which become taxonomy branches.
Synonym discovery. Terms that consistently co-occur in the same cluster but use different surface forms are synonym candidates. Extract them programmatically instead of building synonym lists by hand.
Drift monitoring. Run MeaningFlow monthly. Compare this month’s demand graph against last month’s. New clusters are emerging topics. Growing gaps mean your content is falling behind demand.
Classifier validation. If your content classifier assigns a document to “Hip-Hop” but its embedding sits inside a “Classical” cluster, something is wrong. MeaningFlow acts as a sanity check on any classification system.
The Stack
MeaningFlow is built on:
- Sentence-Transformers for embedding
- UMAP for dimensionality reduction
- HDBSCAN for density-based clustering
- NetworkX for graph construction and analysis
- pgvector-compatible embeddings for integration with Postgres-based knowledge stores
- Neo4j driver for graph database export
Python 3.9+. MIT license. No API keys required — everything runs locally.
Get Started
pip install meaningflow
Or clone and install from source:
git clone https://github.com/Bodhi8/Meaning-Flow.git cd Meaning-Flow pip install -e ".[viz]"
The demo notebook is at notebooks/demo_coverage_gaps.ipynb.
GitHub: github.com/Bodhi8/Meaning-Flow
Where It Fits
MeaningFlow is one piece of a larger knowledge engineering stack. I wrote a two-part series on the full discipline:
- Part 1: Knowledge Engineering for Search and Content: A Practical Guide — the conceptual framework (taxonomy design, classification, entity linking, query understanding, evaluation)
- Part 2: Building a Knowledge Engineering System: An Engineering Guide — the architecture and production patterns (Postgres schema, pipeline orchestration, serving APIs, editorial tooling)
MeaningFlow handles the semantic analysis layer described in both articles — the part that tells you what your taxonomy should look like and where your content gaps are before you build anything else.
If the framework is useful to you, I’d welcome feedback, issues, and contributions on GitHub. And if you’re working on knowledge engineering, content classification, or semantic search — I’d like to hear about it.
Brian Curry is a Kansas City-based data scientist, AI researcher, and founder of Vector1 Research. He builds knowledge engineering systems for enterprise content and search platforms. Previously he founded KC AI Lab, a 1,500-member AI/ML community in Kansas City.
Contact: brian at vector1.ai | Vector1 Research | GitHub


