Skip to content

Repository files navigation

Rhobots

BERTopic-style topic modeling in pure R — no Python, no conda, no reticulate.

Rhobots brings the full BERTopic pipeline to R using only native R packages. Every step — transformer inference, dimensionality reduction, density-based clustering, c-TF-IDF representation, and interactive visualization — runs entirely within your R session.

This package was developed for the Data Analytics for Sustainability course at Utrecht University.


Why Rhobots?

Most R interfaces to large language models require a working Python environment, a conda install, or reticulate to bridge between the two languages. That dependency chain is fragile, version-sensitive, and a real barrier in teaching settings.

Rhobots removes it entirely. Transformer weights are loaded via torch and safetensors, tokenization runs through tok, dimensionality reduction uses uwot, and clustering uses dbscan. The result is a self-contained R package that "just works" in any standard R installation.


Standing on the Shoulders of Giants: BERTopic

Rhobots is a faithful R port of the BERTopic algorithm, which was designed and built by Maarten Grootendorst.

BERTopic is one of the most impressive contributions to the NLP and topic modeling community in recent years. It reimagined topic modeling from the ground up: rather than relying on bag-of-words assumptions like LDA, it leverages state-of-the-art sentence embeddings to capture the true semantic structure of a corpus, then combines UMAP, HDBSCAN, and class-based TF-IDF into an elegant four-stage pipeline that is simultaneously principled and practical.

The Python package is extraordinarily feature-rich — supporting dozens of representation models (KeyBERT, GPT, Zephyr, …), guided topic modeling, multimodal inputs, online learning, and much more. The documentation, tutorials, and the research papers behind the method are all exemplary. If you do any serious NLP work, the Python package is worth your time.

Rhobots would not exist without that foundation. We owe a great debt to Maarten and every contributor to the BERTopic project.


Installation

# install.packages("pak")
pak::pak("JPvdP/Rhobots")

Or clone this repository and install locally:

devtools::install("JPvdP/Rhobots")

Ready-to-Use Models for Scientometrics and Innometrics

Rhobots ships with load_hf_bert(), which can load any BERT-family model directly from the HuggingFace Hub. The following models have been tested and work out of the box for scientometric and innometric analyses (patent texts, scientific abstracts, policy documents):

Model Best for
sentence-transformers/all-MiniLM-L6-v2 Fast general-purpose baseline
allenai/scibert_scivocab_uncased Scientific publications
pritamdeka/S-Scibert-snli-multinli-stsb Scientific sentence similarity
NetworkIsLife/SciBert_Cased_DAFS Domain-adapted scientometrics
anferico/bert-for-patents Patent texts
ProsusAI/finbert Financial / economic texts
library(Rhobots)

# Load a domain-specific encoder
enc <- load_hf_bert("pritamdeka/S-Scibert-snli-multinli-stsb")

# Embed and model
fit <- fit_bertopic(enc, docs = my_abstracts)
print_topics(fit)

Working with Other Models

Not every model on HuggingFace uses the standard BERT weight layout. Rhobots provides lower-level helpers so you can adapt them:

Function Purpose
load_hf_bert(repo_id, weights_path = ...) Load any BERT-family model; supply a local weights_path when the Hub file needs conversion
load_bert_weights(model, weights_path) Load weights manually into a constructed model
make_wordpiece_tokenizer(vocab_file) Build a WordPiece tokenizer from a raw vocab.txt when the repo lacks tokenizer.json
mean_pool(hidden, attention_mask) Mean-pool token hidden states into sentence vectors (the building block for custom pooling strategies)

A typical adaptation workflow for a model with only pytorch_model.bin:

# Convert .bin to .safetensors via the HuggingFace web Space, then:
enc <- load_hf_bert(
  "some-org/some-model",
  weights_path = "/local/path/to/model.safetensors"
)

Core Workflow

library(Rhobots)

# 1. Load an encoder
enc <- load_hf_bert("sentence-transformers/all-MiniLM-L6-v2")

# 2. Compute embeddings (cached to disk so you only pay once)
emb <- embed_texts_cached(enc, docs, cache_file = "embeddings.rds")

# 3. Fit a topic model
fit <- fit_bertopic(
  docs                  = docs,
  embeddings            = emb,
  hdbscan_min_pts       = 5,
  ngram_range           = c(1L, 2L),
  extra_stopwords       = c("study", "paper", "result"),
  reduce_frequent_words = TRUE
)

# 4. Inspect results
print(fit)
print_topics(fit)
get_topic_info(fit)
get_representative_docs(fit, topic = 0)
find_topics(fit, "climate")

Full Feature Overview

Embedding

Function Description
load_hf_bert() Load any BERT-family model from the HuggingFace Hub
embed_texts() Embed a character vector using a loaded encoder
embed_texts_cached() Embed with on-disk caching; subsequent calls load instantly
save_embeddings() / load_embeddings() Persist and reload embedding matrices

Topic Modeling

Function Description
fit_bertopic() Four-stage pipeline: embed → reduce → cluster → c-TF-IDF
print_topics() Console summary of discovered topics

Pluggable Models

Swap in alternative dimensionality-reduction or clustering algorithms by passing a model object to fit_bertopic():

# PCA + k-means (fast, deterministic)
fit <- fit_bertopic(
  docs = docs, embeddings = emb,
  dim_reduction_model = pca_reduction(n_components = 10L),
  cluster_model       = kmeans_clustering(k = 8L)
)

# UMAP + agglomerative clustering
fit <- fit_bertopic(
  docs = docs, embeddings = emb,
  cluster_model = agglomerative_clustering(k = 6L, linkage = "ward.D2")
)

Dimensionality reduction: umap_reduction(), pca_reduction(), no_reduction()

Clustering: hdbscan_clustering(), kmeans_clustering(), agglomerative_clustering()

Accessors (mirroring the Python BERTopic API)

Function Description
get_topics() All topic-term representations as a named list
get_topic() Term-score table for a single topic
get_topic_info() Topic-level metadata (count, label, top terms)
get_document_info() Document-level topic assignments
get_representative_docs() Three documents closest to each topic centroid
find_topics() Rank topics by similarity to a search term

Out-of-Sample Prediction

result <- transform_bertopic(fit, new_docs, encoder = enc)
# result$topics         — assigned topic IDs
# result$probabilities  — cosine similarity to assigned centroid

Post-Fit Topic Manipulation

Function Description
reduce_topics(fit, nr_topics) Iteratively merge the most similar topics
reduce_outliers() Reassign noise documents to the nearest real topic
merge_topics() Manually collapse a set of topics into one
apply_mmr() Refine topic terms with Maximal Marginal Relevance

Dynamic Topic Modeling

# Single model, topics tracked across timestamps
tot <- topics_over_time(fit, timestamps = df$Year)
visualize_topics_over_time(tot)

# Independent model per period, transitions aligned by centroid similarity
flow <- fit_topics_over_time(enc, docs, timestamps = df$Year)
visualize_topic_flow(flow, color_by = "status")

Visualization (requires plotly)

Function Description
visualize_topics() 2-D UMAP scatter plot coloured by topic
visualize_barchart() Grid of c-TF-IDF bar charts, one panel per topic
visualize_topics_over_time() Line chart of topic frequency over time
visualize_topic_flow() Sankey diagram of topic transitions across periods

Stopwords

# Built-in English list
get_stopwords("english")

# Load domain-specific stopwords from a file, CSV, or character vector
sw <- load_stopwords("domain_stopwords.txt")

fit <- fit_bertopic(docs = docs, embeddings = emb,
                    extra_stopwords = sw)

Dependencies

All dependencies are CRAN or R-universe packages — no Python required.

Package Role
torch Transformer forward passes
safetensors Safe, fast weight loading
hfhub HuggingFace Hub downloads
tok Fast tokenizer (HuggingFace format)
wordpiece Fallback WordPiece tokenizer
uwot UMAP dimensionality reduction
dbscan HDBSCAN clustering
Matrix Sparse document-term matrices
plotly (suggested) Interactive visualizations

Acknowledgements

This package was built for the Data Analytics for Sustainability course at Utrecht University, Faculty of Geosciences.

The algorithm and API design are based on, and inspired by, BERTopic by Maarten Grootendorst and its many contributors. Please cite the original work if you publish results obtained with this package:

Grootendorst, M. (2022). BERTopic: Neural topic modeling with a class-based TF-IDF procedure. arXiv preprint arXiv:2203.05794. https://arxiv.org/abs/2203.05794


License

MIT © J.P.G. van der Pol, Utrecht University

Releases

Packages

Contributors

Languages