
    Wi$                     ^    d dl Zd dlmZ d dlmZ d dlmZ d dlm	Z	 d dl
mZ  G d de      Zy)	    N)chain)List)sparse)
csr_matrix)CountVectorizerc                   n     e Zd ZdZddedz  dedz  f fdZdee   ddfdZdee   de	fd	Z
dd
Z xZS )OnlineCountVectorizera	  An online variant of the CountVectorizer with updating vocabulary.

    At each `.partial_fit`, its vocabulary is updated based on any OOV words
    it might find. Then, `.update_bow` can be used to track and update
    the Bag-of-Words representation. These functions are separated such that
    the vectorizer can be used in iteration without updating the Bag-of-Words
    representation can might speed up the fitting process. However, the
    `.update_bow` function is used in BERTopic to track changes in the
    topic representations and allow for decay.

    This class inherits its parameters and attributes from:
        `sklearn.feature_extraction.text.CountVectorizer`

    Arguments:
        decay: A value between [0, 1] to weight the percentage of frequencies
               the previous bag-of-words should be decreased. For example,
               a value of `.1` will decrease the frequencies in the bag-of-words
               matrix with 10% at each iteration.
        delete_min_df: Delete words at each iteration from its vocabulary
                       that are below a minimum frequency.
                       This will keep the resulting bag-of-words matrix small
                       such that it does not explode in size with increasing
                       vocabulary. If `decay` is None then this equals `min_df`.
        **kwargs: Set of parameters inherited from:
                  `sklearn.feature_extraction.text.CountVectorizer`
                  In practice, this means that you can still use parameters
                  from the original CountVectorizer, like `stop_words` and
                  `ngram_range`.

    Attributes:
        X_ (scipy.sparse.csr_matrix) : The Bag-of-Words representation

    Examples:
    ```python
    from bertopic.vectorizers import OnlineCountVectorizer
    vectorizer = OnlineCountVectorizer(stop_words="english")

    for index, doc in enumerate(my_docs):
        vectorizer.partial_fit(doc)

        # Update and clean the bow every 100 iterations:
        if index % 100 == 0:
            X = vectorizer.update_bow()
    ```

    To use the model in BERTopic:

    ```python
    from bertopic import BERTopic
    from bertopic.vectorizers import OnlineCountVectorizer

    vectorizer_model = OnlineCountVectorizer(stop_words="english")
    topic_model = BERTopic(vectorizer_model=vectorizer_model)
    ```

    References:
        Adapted from: https://github.com/idoshlomo/online_vectorizers
    Ndecaydelete_min_dfc                 H    || _         || _        t        t        |   di | y )N )r
   r   superr	   __init__)selfr
   r   kwargs	__class__s       k/home/sietch6/trending-topics-pipeline/venv/lib/python3.12/site-packages/bertopic/vectorizers/_online_cv.pyr   zOnlineCountVectorizer.__init__G   s%    
*#T3=f=    raw_documentsreturnc                 *   t        | d      s| j                  |      S | j                         }|D cg c]
  } ||       }}t        t	        j
                  |            }|j                  t        | j                  j                                     }|ryt        | j                  j                               }t        t        |t        t        |dz   |dz   t        |      z   d                        }| j                  j!                  |       | S c c}w )zPerform a partial fit and update vocabulary with OOV tokens.

        Arguments:
            raw_documents: A list of documents
        vocabulary_   )hasattrfitbuild_analyzersetr   from_iterable
differencer   keysmaxvaluesdictziplistrangelenupdate)	r   r   analyzerdocanalyzed_documents
new_tokens
oov_tokens	max_indexoov_vocabularys	            r   partial_fitz!OnlineCountVectorizer.partial_fitL   s     t]+88M**&&(7DEhsmEE,,-?@A
**3t/?/?/D/D/F+GH
D,,3356I!y1}i!mc*o.MqQRN ##N3 Fs   Dc                    t        | d      rB| j                  |      }t        | j                  j                  d   |j                  d   | j                  j                  d   z
  ft
              }t        j                  | j                  |g      | _        t        |j                  d   | j                  j                  d   z
  | j                  j                  d   ft
              }t        j                  | j                  |g      | _        | j                  !| j                  d| j                  z
  z  | _        | xj                  |z  c_        n| j                  |      | _        | j                  | j                          | j                  S )as  Create or update the bag-of-words matrix.

        Update the bag-of-words matrix by adding the newly transformed
        documents. This may add empty columns if new words are found and/or
        add empty rows if new topics are found.

        During this process, the previous bag-of-words matrix might be
        decayed if `self.decay` has been set during init. Similarly, words
        that do not exceed `self.delete_min_df` are removed from its
        vocabulary and bag-of-words matrix.

        Arguments:
            raw_documents: A list of documents

        Returns:
            X_: Bag-of-words matrix
        X_r   r   )dtype)r   	transformr   r2   shapeintr   hstackvstackr
   r   
_clean_bow)r   r   Xcolumnsrowss        r   
update_bowz OnlineCountVectorizer.update_bowf   s#   $ 4}-A !$''--"2AGGAJqAQ4Q!RZ]^GmmTWWg$67DG qwwqzDGGMM!,<<dggmmA>NOWZ[DmmTWWdO4DG zz%''Q^4GGqLGnn]3DG)OOwwr   c                    t        j                  | j                  j                  d      | j                  k\        d   }|D ci c]  }|| }}| j                  dd|f   | _        i }| j
                  j                         D ci c]  \  }}||
 }}}t        |      D ]  \  }}|j                  |      ||||   <   ! || _        yc c}w c c}}w )z5Remove words that do not exceed `self.delete_min_df`.r   r   N)	npwherer2   sumr   r   items	enumerateget)	r   indicesindexindices_dict	new_vocabkvvocabulary_dictis	            r   r9   z OnlineCountVectorizer._clean_bow   s     ((477;;q>T-?-??@C29:u::''!W*% 	,0,<,<,B,B,DEDAq1a4EE!'* 	6HAu&245	/%01	6 % ;
 Fs   
CC)NN)r   N)__name__
__module____qualname____doc__floatr   r   strr0   r   r=   r9   __classcell__)r   s   @r   r	   r	      sX    9v>edl >%$, >
c t 4(S	 (j (T%r   r	   )numpyr?   	itertoolsr   typingr   scipyr   scipy.sparser   sklearn.feature_extraction.textr   r	   r   r   r   <module>rZ      s%        # ;S%O S%r   