TopicWizard

repository·main·Indexed 40 days ago

https://github.com/x-tabdeveloping/topicwizard

A Python library for opinionated topic model visualization (v1.1.4) that uses interactive Plotly figures to investigate relations between topics, words, documents, and groups. It provides a web application via `topicwizard.visualize()`, a figures API for standalone plots, and compatibility wrappers for scikit-learn, Gensim, and BERTopic models.

Tokens
12.3K
Snippets
59
Records
62
Agent score
97%

What's inside TopicWizard

  1. What is TopicData and how is it used

    main

    The TopicData object is the central abstraction in topicwizard. It encapsulates all information regarding topical inference within a corpus, allowing you to reproduce interpretive visualizations in both the web app and individual figures.

    Because TopicData is implemented as a Python TypedDict, it behaves like a standard dictionary at runtime, making it highly interoperable with other Python libraries. However, it provides static type checking for developers using tools like Pyright.

    You can pass a TopicData object to visualization utilities to recreate specific plots or launch the full web application interface.

    import topicwizard
    from topicwizard.figures import topic_map
    
    # topic_map accepts a TopicData object
    topic_map(topic_data)
  2. How topic pipelines work in topicwizard

    main

    topicwizard uses the TopicPipeline abstraction to handle classical topic models (those using the bag-of-words assumption). A topic pipeline typically consists of a Vectorizer (which converts text into bag-of-words vectors, e.g., sklearn.feature_extraction.text.CountVectorizer) and a Topic Model (a decomposition model that turns document-term matrices into document-topic matrices, e.g., sklearn.decomposition.LatentDirichletAllocation or sklearn.decomposition.NMF).

    To be compatible with topicwizard, a topic model must have a .components_ attribute representing the topic-term importance matrix. While you can use standard scikit-learn Pipeline objects, topicwizard works best with TopicPipeline, which provides enhanced features for model interpretation and downstream tasks.

    from sklearn.feature_extraction.text import CountVectorizer
    from sklearn.decomposition import LatentDirichletAllocation
    from topicwizard.pipeline import make_topic_pipeline
    
    vectorizer = CountVectorizer()
    model = LatentDirichletAllocation(n_components=10)
    
    topic_pipeline = make_topic_pipeline(vectorizer, model)
  3. Work with TopicData objects

    main

    A TopicData object is a serialized representation of the topical inference and model fit results. It is essentially a typed dictionary containing all information needed for visualization.

    Generating TopicData:

    • Use pipeline.prepare_topic_data(corpus) for TopicPipeline objects.
    • Call model.prepare_topic_data(corpus) for compatible contextual models (like turftopic or BERTopicWrapper).

    Saving and Loading: Use joblib to serialize TopicData for sharing or deployment. Note that version 1.0.0+ is not fully backwards compatible with older TopicData files.

    import joblib
    from topicwizard.data import TopicData
    
    # Generate
    topic_data = pipeline.prepare_topic_data(corpus)
    
    # Save
    joblib.dump(topic_data, "topic_data.joblib")
    
    # Load
    topic_data: TopicData = joblib.load("topic_data.joblib")
    
    # Use in visualization
    topicwizard.visualize(topic_data=topic_data)
  4. How topic pipelines work

    main

    For classical/bag-of-words models, topicwizard uses a topic pipeline abstraction. A pipeline consists of two main components:

    1. A vectorizer: transforms raw text into bag-of-words representations (e.g., sklearn.feature_extraction.text.CountVectorizer).
    2. A topic model: decomposes these representations into topic vectors (e.g., sklearn.decomposition.NMF).

    You can use standard scikit-learn pipelines or wrap them in topicwizard's TopicPipeline to enable advanced visualization features.

    from sklearn.feature_extraction.text import CountVectorizer
    from sklearn.decomposition import NMF
    from topicwizard.pipeline import make_topic_pipeline
    
    vectorizer = CountVectorizer(min_df=5, max_df=0.8, stop_words="english")
    model = NMF(n_components=10)
    
    topic_pipeline = make_topic_pipeline(vectorizer, model)
  5. Use Turftopic instead of Top2Vec or CTM

    main

    Direct support for Top2Vec and CTM is not provided because their functionality is natively covered by turftopic.

    • For Top2Vec behavior, use turftopic.ClusteringTopicModel.
    • For CTM behavior, use turftopic.AutoEncodingTopicModel.

    To use these, you must install turftopic, umap-learn, and scikit-learn>=1.3.0.

    pip install turftopic umap-learn 'scikit-learn>=1.3.0'
    from turftopic import ClusteringTopicModel, AutoEncodingTopicModel
    import umap
    from sklearn.cluster import HDBSCAN
    import topicwizard
    
    # Top2Vec-like behavior
    top2vec_style = ClusteringTopicModel(
        dimensionality_reduction=umap.UMAP(n_neighbors=15, n_components=5, metric="cosine"),
        clustering=HDBSCAN(min_cluster_size=15, metric="euclidean", cluster_selection_method="eom"),
        feature_importance="centroid",
    )
    topicwizard.visualize(corpus, model=top2vec_style)
    
    # CTM-like behavior
    ctm_style = AutoEncodingTopicModel(10, combined=True)
    topicwizard.visualize(corpus, model=ctm_style)
  6. Launch the TopicWizard Web Application

    main

    The easiest way to use topicwizard is through its interactive visualization dashboard. You can launch this dashboard using the topicwizard.visualize() function.

    topicwizard supports several input types:

    • Classical Topic Models: Models wrapped in a topicwizard.pipeline.make_topic_pipeline.
    • Contextually Sensitive Models: Models like those from turftopic.
    • Corpus + Model: A raw corpus (list of texts) and a trained model.
    • TopicData object: A pre-computed TopicData object.

    By default, the application opens three pages: Topics, Words, and Documents. If you have gold standard group labels, you can pass them via group_labels to enable a Groups page.

    import topicwizard
    
    # Using a pipeline model
    topicwizard.visualize(texts, model=pipeline)
    
    # Using a TopicData object
    topicwizard.visualize(topic_data=topic_data)
  7. Use contextually sensitive topic models with Turftopic

    main

    Topicwizard provides native support for contextual topic models from the turftopic package. These models move beyond the bag-of-words assumption to capture contextual nuances.

    You can use these models in two ways:

    1. Pre-compute topic data: Use the model's prepare_topic_data(corpus) method to create a topic_data object. This is the preferred method because the data can be saved, allowing you to restart the app or generate individual figures later without re-running the model.
    2. Direct visualization: Pass both the corpus and the model directly to topicwizard.visualize().
    import topicwizard
    from turftopic import SemanticSignalSeparation
    
    model = SemanticSignalSeparation(n_components=10)
    
    # Option 1: Pre-compute topic data (Preferred)
    topic_data = model.prepare_topic_data(corpus)
    topicwizard.visualize(topic_data=topic_data)
    
    # Option 2: Run directly with model and corpus
    topicwizard.visualize(corpus, model=model)
  8. Freeze a TopicPipeline for downstream tasks

    main

    If you want to use a trained topic model as a fixed feature extractor in a larger pipeline (e.g., a classification pipeline), you should set topic_pipeline.freeze = True. This prevents the vectorizer and topic model from being re-trained when .fit() or .partial_fit() is called on the outer pipeline.

    from sklearn.pipeline import make_pipeline
    from sklearn.linear_model import LogisticRegression
    
    # 1. Train and investigate the topic model
    topic_pipeline = make_topic_pipeline(vectorizer, model).fit(texts)
    topicwizard.visualize(topic_pipeline)
    
    # 2. Freeze the topic model so it acts as a fixed feature extractor
    topic_pipeline.freeze = True
    
    # 3. Use it in a larger pipeline
    cls_pipeline = make_pipeline(topic_pipeline, LogisticRegression())
    cls_pipeline.fit(X, y)
  9. Use BERTopic models with topicwizard

    main

    BERTopic models are supported natively via the BERTopicWrapper. You can wrap a BERTopic model and then either launch the topicwizard web app immediately or generate a TopicData object for persistence or custom figures.

    from bertopic import BERTopic
    from topicwizard.compatibility import BERTopicWrapper
    import topicwizard
    
    # Wrap the model
    model = BERTopic(language="english")
    wrapped_model = BERTopicWrapper(model)
    
    # Option 1: Start the web app immediately
    topicwizard.visualize(corpus, model=wrapped_model)
    
    # Option 2: Produce a TopicData object for persistence
    topic_data = wrapped_model.prepare_topic_data(corpus)
  10. Create a compatible topic model pipeline

    main

    To use classical models (like Scikit-learn's NMF) with topicwizard, you must wrap your vectorizer and model in a make_topic_pipeline. This ensures the pipeline is compatible with the visualization requirements.

    Steps:

    1. Initialize a vectorizer (e.g., CountVectorizer).
    2. Initialize a decomposition model (e.g., NMF).
    3. Use make_topic_pipeline(vectorizer, model) to create the pipeline.
    4. Call .fit(texts) on the pipeline.
    from sklearn.decomposition import NMF
    from sklearn.feature_extraction.text import CountVectorizer
    from topicwizard.pipeline import make_topic_pipeline
    
    bow_vectorizer = CountVectorizer()
    nmf = NMF(n_components=10)
    pipeline = make_topic_pipeline(bow_vectorizer, nmf)
    pipeline.fit(texts)
  11. Use easy_deploy() for automated Docker deployment

    main

    Starting in version 1.1.0, you can use topicwizard.easy_deploy() to automatically generate a deployment directory containing a Dockerfile, a main.py entrypoint, and your topic_data.joblib file. This directory is ready to be used with Docker or cloud platforms like HuggingFace Spaces.

    import joblib
    import topicwizard
    
    # Load previously produced topic_data object
    topic_data = joblib.load("topic_data.joblib")
    
    # Generate the deployment folder
    topicwizard.easy_deploy(topic_data, dest_dir="deployment", port=7860)
  12. Build a Dash application from TopicData

    main

    If you already have a TopicData object, you can wrap it in a Dash application using topicwizard.get_dash_app(topic_data). This allows you to host the topic wizard interface as a web server.

    # main.py
    import topicwizard
    
    # Assuming topic_data is already defined
    app = topicwizard.get_dash_app(topic_data)
    
    if __name__ == "__main__":
        app.run_server(debug=False, port=8050)