Skip to content

Repository files navigation

Audience Segmentation Tool

tests Python 3.12 uv License MIT

An end-to-end, reproducible NLP pipeline that turns synthetic prospect and deal-history data into named audience segments, rule-based outreach guidance, and reviewable artifacts.

Resume claim: Built an NLP segmentation pipeline for 500 prospects using TF-IDF, UMAP, K-Means, and DBSCAN; delivered CLI and Streamlit outputs with named clusters and outreach recommendations.

Review it in five commands

uv sync --locked
uv run python -m unittest discover -s tests -v
uv run python generate_data.py
uv run python segment.py --input data/prospects.csv --deals data/deal_history.csv --clusters auto --output results
uv run python scripts/verify_artifacts.py

Then launch the same results through the interactive interface:

uv run streamlit run app.py

The project uses uv exclusively. .python-version pins Python 3.12 and uv.lock pins the complete environment.

Executable reviewer notebook

Open the raw-data-to-validation tutorial, or launch it from the repository root:

uv sync --locked --group notebook
uv run --group notebook jupyter lab notebooks/01_data_to_validation.ipynb

The notebook degrades the generated prospect and deal exports, proves exact schema and row recovery, then executes the real TF-IDF/UMAP/K-Means/DBSCAN pipeline and repository tests. CI executes every cell without modifying the committed notebook.

System design

flowchart LR
    P["Synthetic prospects\n500 rows"] --> J["Validated company join"]
    D["Synthetic deal history\n200 rows"] --> A["Per-company aggregates\ncount, mean value, win rate, cycle"]
    A --> J
    J --> F["Feature pipeline\nTF-IDF + UMAP/PCA + scaling"]
    F --> K["K-Means\nautomatic elbow selection"]
    F --> B["DBSCAN\ncomparison"]
    K --> O["CSV + JSON + HTML + Markdown"]
    B --> O
    O --> C["CLI"]
    O --> S["Streamlit viewer"]
Loading

The clustering matrix combines two reduced text representations with eight scaled numeric features:

  • website descriptions and recent campaign text become TF-IDF vectors, then UMAP or PCA components;
  • prospect revenue, employee count, social score, and estimated ad spend provide commercial context;
  • actual aggregates from deal_history.csv add deal count, mean deal value, win rate, and mean sales-cycle duration.

K-Means is the primary segmentation method. DBSCAN is a comparison view, not an accuracy validator. Segment names and outreach text are deterministic rules derived from cluster profiles; they are not generated by an LLM.

Output contract

The CLI always writes four artifacts to the selected output directory:

Artifact Review purpose
segments.csv Source fields, deal aggregates, cluster assignment, name, and 2-D projection for all 500 prospects
segment_profiles.json K-Means and DBSCAN profile summaries
visualization.html Self-contained, interactive Plotly scatter plot
report.md Human-readable profiles and rule-based outreach recommendations

scripts/verify_artifacts.py fails closed if the row counts, deal integration, named profiles, projection columns, or visualization contract is broken. The integration test also runs the PCA pipeline twice and compares SHA-256 hashes for every artifact.

CLI

--input       Prospect CSV (default: data/prospects.csv)
--deals       Deal-history CSV (default: data/deal_history.csv)
--clusters    Integer or auto elbow selection (default: auto)
--output      Artifact directory (default: results/)
--no-umap     Use PCA instead of UMAP
--no-dbscan   Skip the DBSCAN comparison
--verbose     Enable debug logging

Repository map

.
├── .github/workflows/tests.yml  # public Ubuntu release gate
├── data/                        # generated and ignored
├── notebooks/01_data_to_validation.ipynb
├── pipeline/
│   ├── text_processor.py        # TF-IDF, reduction, numeric scaling
│   └── segmentation.py          # K-Means, DBSCAN, profiles, naming
├── results/                     # generated and ignored
├── scripts/verify_artifacts.py
├── tests/test_pipeline.py
├── app.py                       # Streamlit viewer
├── generate_data.py             # deterministic synthetic inputs
├── segment.py                   # shared CLI/app orchestration
├── pyproject.toml
└── uv.lock

Evidence and boundaries

  • The included generator creates fictional companies and transactions from authored templates. No performance claim is based on customer or employer data.
  • Clusters are descriptive, not ground truth. Their usefulness must be evaluated with domain experts and downstream campaign outcomes before real use.
  • Revenue, ad spend, and outreach guidance are illustrative. They are not financial forecasts or autonomous sales instructions.
  • UMAP and K-Means are seeded. Exact repeatability is tested on the PCA path because native numerical libraries can introduce platform-level floating-point variation.
  • The public GitHub workflow installs only from uv.lock, checks Ruff formatting and lint, runs integration tests, executes the full UMAP pipeline, validates artifacts, and smoke-tests Streamlit.

See MODEL_CARD.md for intended use and limitations and VERIFICATION.md for the recorded release evidence.

Local pre-push gate

GitHub Actions is authoritative. To run the same locked lint and test checks before a local push:

git config core.hooksPath .githooks

The committed hook invokes only uv sync --locked and uv run; it does not use a system Python environment.

License

MIT

About

NLP + unsupervised learning pipeline for prospect clustering — TF-IDF, UMAP, K-Means with auto-named segments and outreach strategies

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages