MaartenGr / MaartenGr/BERTopic
BERTopic.load(path, embedding_model=...) makes a redundant HuggingFace network request even when an embedder is explicitly provided
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 7.8k
- Forks
- 920
- Avg merge
- 22h 24m
- Merged PRs (30d)
- 5
Description
Describe the bug
When calling BERTopic.load(path, embedding_model=my_embedder), BERTopic unconditionally fetches the embedding model from HuggingFace. This happens even when the caller already supplied one such model. The downloaded model is immediately discarded and overwritten by the caller's embedding_model.
The cause is in _create_model_from_files: it calls SentenceTransformer(params["embedding_model"]) (using the bare name stored in the saved config) before the caller's embedding_model argument is ever consulted.
# _create_model_from_files that runs unconditionally, even when embedding_model is passed
try:
from sentence_transformers import SentenceTransformer
embedding_model = select_backend(SentenceTransformer(params["embedding_model"])) # network call
except:
embedding_model = BaseEmbedder()
...
# Back in BERTopic.load() — the caller's model overwrites the downloaded one
if embedding_model is not None:
topic_model.embedding_model = select_backend(embedding_model, ...)
Impact
- Causes outbound HTTPS calls to
huggingface.cowhen the user has explicitly provided a local embedder and expects no network I/O. - In air-gapped or offline environments this produces SSL errors and retries. These are silently swallowed by a bare except: — which is dangerous regardless — leaving the service appearing to work correctly. The issue only surfaces when inspecting network traffic.
HF_HUB_OFFLINE=1is an effective workaround but the root cause is in BERTopic.
Steps to reproduce
from sentence_transformers import SentenceTransformer
from bertopic import BERTopic
# Load a local embedder explicitly
local_embedder = SentenceTransformer("path/to/local/model", local_files_only=True)
# BERTopic will still attempt to fetch from HF despite local_embedder being provided
topic_model = BERTopic.load("path/to/saved/bertopic", embedding_model=local_embedder)
Expected behavior
When embedding_model is explicitly provided to BERTopic.load(), no network request should be made. The auto-load from HF should be skipped entirely.
Proposed fix
Add embedding_model=None to _create_model_from_files and guard the SentenceTransformer() call:
if embedding_model is None:
try:
from sentence_transformers import SentenceTransformer
embedding_model = select_backend(SentenceTransformer(params["embedding_model"]))
except:
...
else:
embedding_model = select_backend(embedding_model)
As a secondary improvement, the bare except: could be narrowed to except Exception: to avoid swallowing things like KeyboardInterrupt and SystemExit.
I have a PR ready against this fix if the approach is agreeable.
Thanks!
Versions
bertopic==0.17.4sentence-transformers==5.2.2
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at BERTopic.load and _create_model_from_files, using the supplied local-embedder reproduction to trace when SentenceTransformer(params["embedding_model"]) is invoked. Done means an explicitly provided embedding model loads without a HuggingFace network request while the existing file-loading behavior remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- machine-learning
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 30/100