Skip to main content

topiclayers

From posts to topical multilayer networks — hardened and social-scientist-friendly.

Quickstart

# Requires Python 3.12
pip install topiclayers

# copy runnable examples (configs + toy data) into ./examples/
topiclayers init

topiclayers run examples/generic.yml

That's it. You get a GML network file in ./out/generic_toy/networks/.

What does it do?

  1. Loads your posts (Twitter JSONL, CSV, Parquet).
  2. Cleans text (removes URLs, @mentions, newlines).
  3. Models topics using BERTopic with SentenceTransformer embeddings.
  4. Labels topics with an LLM (local via Ollama by default) and propagates topic labels through retweet chains.
  5. Builds networks: single-layer retweet, multilayer per-topic, and bipartite temporal-text networks.

Minimal config

Save this as my_config.yml:

input:
  format: csv_posts
  posts: my_data.csv

name: my_dataset

topic_model:
  embedder: all-MiniLM-L6-v2
  min_topic_size: 50

network:
  type: multilayer_repost

output_dir: ./out/my_dataset

Run it: topiclayers run my_config.yml

Checking progress

Long runs write a live status file to <output_dir>/run_status.json. Check the current stage, elapsed time, and ETA from another terminal without touching the running job:

topiclayers status out/my_dataset

Example output:

Stage 3/7: embed
Status: running
Run: my_dataset
Progress: 412000/1200000 (34%)
Stage elapsed: 18m 12s
Stage ETA: ~35m 20s
Total elapsed: 21m 05s

Stages are load → data → embed → topic_model → label → network → manifest. Stages with a per-item counter (data, embed, network) report a live ETA. Opaque stages (BERTopic's UMAP+HDBSCAN) fall back to the median duration of past runs, stored in <output_dir>/cache/stage_timings.json.

Topic labeling with an LLM (optional)

After clustering, the pipeline can ask a local LLM to write one short, readable label per topic (instead of raw keyword lists like -1_proclamation_plante_trending). Default is Ollama — free, local, nothing leaves your machine:

# one-time setup
pip install 'topiclayers[labeling]'
ollama pull qwen2.5:7b

# start the server in another terminal
ollama serve

Then just run the pipeline as usual (label_model is on by default). Any LiteLLM model string works:

topic_model:
  label_model: ollama/qwen2.5:7b      # default
  # label_model: gpt-4o-mini          # OpenAI (needs OPENAI_API_KEY)
  # label_model: anthropic/claude-3-haiku-20240307
  # label_model: ""                   # disable labeling

Custom / self-hosted OpenAI-compatible endpoints

Any server speaking the OpenAI protocol (Unsloth, llama.cpp, vLLM, LM Studio...) works via label_api_base:

topic_model:
  label_model: openai/unsloth/Qwen3.8-27B-GGUF   # note the openai/ prefix
  label_api_base: http://localhost:8888/v1

with the token in .env (key resolution order: LABEL_API_KEYOPENAI_LIKE_API_KEYOPENAI_API_KEY). You can also set LABEL_API_BASE in .env instead of the YAML. Find the exact model name your server exposes with curl http://localhost:8888/v1/models.

Labeling is non-fatal: if the model server is unreachable, topics keep their keyword labels and everything else proceeds normally.

Input formats

Format Extension Description
twitter_jsonl .json, .jsonl Twitter/X API v2 JSONL
csv_posts .csv Generic CSV with post_id, user_id, text columns
parquet_posts .parquet Same schema as CSV, Parquet format

CSV optional columns: created_at, lang, interaction_type (original/repost/quote/reply), target_post_id, mentions (semicolon-separated), extra_* passthrough columns.

What if something fails?

Symptom Likely cause Fix
"All topics are -1" / "no topics found" min_topic_size too high or dataset too small Halve min_topic_size in config, or use a larger dataset (>100 posts)
"Module not found" topiclayers not installed pip install topiclayers
topiclayers: command not found installed in a venv that isn't active Activate the venv (source .venv/bin/activate) or use python -m topiclayers.cli; on install with --user add ~/.local/bin to PATH
"OpenAI API key not set" Using OpenAI embedder without key Switch embedder to all-MiniLM-L6-v2 (default, works offline)
"Qdrant connection refused" Qdrant vector DB not running Ignore — Qdrant is optional. Set QDRANT_URL in .env to enable
"Cannot create multilayer network" All posts are outliers Reduce min_topic_size or provide more data
"UMAP spectral layout failed" Dataset too small (<10 posts) Topic modeling needs more data; consider using topic labels from elsewhere

Output files

For a dataset named <name> (e.g. my_dataset), output goes to <output_dir>/:

<output_dir>/
├── run_manifest.json              # Reproducibility metadata
├── run_status.json                # Live stage/ETA tracking (while running)
├── cache/
│   └── data/
│       ├── tweets_<name>.pkl/.csv          # Full tweet table
│       ├── retweet_labeled_<name>.pkl/.csv # Retweets with topic labels
│       └── manifest_<name>.json            # Cache validity key
│   └── stage_timings.json         # Per-stage durations for ETA prediction
└── networks/
    ├── <name>_retweet.gml                  # Single-layer retweet network
    ├── <name>_retweet_network_ml.gml       # Multilayer (uunet format)
    ├── <name>_ttt.gml                      # Temporal-text bipartite network
    └── projected/
        └── <name>__prj_<topic>.gml         # Per-topic projected networks

Requirements

  • Python 3.12 (uunet, used for multilayer networks, does not ship wheels for 3.13+ yet)
  • Optional: Ollama + topiclayers[labeling] extra (LLM topic labeling), Docker (for Qdrant vector search), OpenAI API key (for OpenAI embeddings)

Planned: JOSS software paper

Once the API stabilises and the PLOS ONE core paper results are regenerated with this library, a short JOSS (Journal of Open Source Software) paper will be submitted with a Zenodo DOI.

Download files

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

Source Distribution

topiclayers-0.2.1.tar.gz (30.6 kB view details)

Uploaded Source

Built Distribution

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

topiclayers-0.2.1-py3-none-any.whl (37.2 kB view details)

Uploaded Python 3

File details

Details for the file topiclayers-0.2.1.tar.gz.

File metadata

  • Download URL: topiclayers-0.2.1.tar.gz
  • Upload date:
  • Size: 30.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for topiclayers-0.2.1.tar.gz
Algorithm Hash digest
SHA256 9b64b1fc3bd48c70f064b6ac471ac1e28ab59e45d82401e809d28d70eea0f096
MD5 459366efa82fd3f941a39ecddda26ec1
BLAKE2b-256 e60ff102e30fd1c3898f807adf89920a42beadc9e830eb0367056a2ac52a8eb1

See more details on using hashes here.

Provenance

The following attestation bundles were made for topiclayers-0.2.1.tar.gz:

Publisher: publish.yml on alessiogandelli/topiclayers

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

File details

Details for the file topiclayers-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: topiclayers-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 37.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for topiclayers-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cbd80ff0171d7c1041478c3b93384dec8ef707235b00bb3a7ad9b92bd7a24886
MD5 6646d22090dcefd7b55b95c4242e7816
BLAKE2b-256 954184f083c26917b616efe8e60e67e8e32cb0d3c787985bb6811b64c26a3d08

See more details on using hashes here.

Provenance

The following attestation bundles were made for topiclayers-0.2.1-py3-none-any.whl:

Publisher: publish.yml on alessiogandelli/topiclayers

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

Release history Release notifications | RSS feed

0.3.0

2 files

This release

0.2.1 This release

2 files

0.2.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page