
    ^Nj0                     X   U d dl Z d dlmZ d dlmZ d dlmZ d dlmZm	Z	m
Z
 d dlZd dlZd dlmZ d dlmZmZmZmZ d dlmZmZ d d	lmZmZ d d
lmZ d dlmZmZ g dZ  edd ddd ed      e D  cg c]  } |  d	 c} dd	      gZ!e"e   e#d<    G d de      Z$ G d de      Z%yc c} w )    N)defaultdict)get_all_start_methods)Path)AnyIterableType)SnowballStemmer)define_cache_dir
iter_batchget_all_punctuationremove_non_alphanumeric)ParallelWorkerPoolWorker)SparseEmbeddingSparseTextEmbeddingBase)SimpleTokenizer)SparseModelDescriptionModelSource)arabicdanishdutchenglishfinnishfrenchgermangreek	hungarianitalian	norwegian
portugueseromanianrussianspanishswedishtamilturkishzQdrant/bm25z6BM25 as sparse embeddings meant to be used with Qdrantz
apache-2.0g{Gz?)hf.txtTz	mock.file)	model
vocab_sizedescriptionlicense
size_in_GBsourcesadditional_filesrequires_idf
model_filesupported_bm25_modelsc                       e Zd ZdZ	 	 	 	 	 	 	 	 d$dededz  dedededed	ed
ededz  def fdZ	e
dee   fd       Ze
dededee   fd       Z	 	 	 	 d%dededeee   z  dededz  dededz  dee   fdZ	 	 d&deee   z  dededz  dedee   f
dZdee   dee   fdZdee   dee   fdZdeee   z  dedefdZdee   deeef   fdZe
dedefd       Zd eee   z  dedee   fd!Ze
ded"   fd#       Z xZS )'Bm25a  Implements traditional BM25 in a form of sparse embeddings.
    Uses a count of tokens in the document to evaluate the importance of the token.

    WARNING: This model is expected to be used with `modifier="idf"` in the sparse vector index of Qdrant.

    BM25 formula:

    score(q, d) = SUM[ IDF(q_i) * (f(q_i, d) * (k + 1)) / (f(q_i, d) + k * (1 - b + b * (|d| / avg_len))) ],

    where IDF is the inverse document frequency, computed on Qdrant's side
    f(q_i, d) is the term frequency of the token q_i in the document d
    k, b, avg_len are hyperparameters, described below.

    Args:
        model_name (str): The name of the model to use.
        cache_dir (str, optional): The path to the cache directory.
            Can be set using the `FASTEMBED_CACHE_PATH` env variable.
            Defaults to `fastembed_cache` in the system's temp directory.
        k (float, optional): The k parameter in the BM25 formula. Defines the saturation of the term frequency.
            I.e. defines how fast the moment when additional terms stop to increase the score. Defaults to 1.2.
        b (float, optional): The b parameter in the BM25 formula. Defines the importance of the document length.
            Defaults to 0.75.
        avg_len (float, optional): The average length of the documents in the corpus. Defaults to 256.0.
        language (str): Specifies the language for the stemmer.
        disable_stemmer (bool): Disable the stemmer.
    Raises:
        ValueError: If the model_name is not in the format <org>/<model> e.g. BAAI/bge-base-en.
    N
model_name	cache_dirkbavg_lenlanguagetoken_max_lengthdisable_stemmerspecific_model_pathkwargsc
                    t        |   ||fi |
 |t        vrt        | d      || _        || _        || _        || _        | j                  |      }t        t        |            | _        |	| _        | j                  || j                  | j                  | j                        | _        || _        t#        t%                     | _        || _        |r"t#               | _        d | _        t2        | _        y t#        | j/                  | j                  | j                              | _        t1        |      | _        t2        | _        y )Nz language is not supported)local_files_onlyr=   )super__init__supported_languages
ValueErrorr:   r7   r8   r9   _get_model_descriptionstrr
   r6   _specific_model_pathdownload_model_local_files_only
_model_dirr;   setr   punctuationr<   	stopwordsstemmer_load_stopwordsr	   r   	tokenizer)selfr5   r6   r7   r8   r9   r:   r;   r<   r=   r>   model_description	__class__s               f/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/fastembed/sparse/bm25.pyrB   zBm25.__init__[   s$    	Y9&9..z)CDEE$DM 77
C-i89$7!--NN!33 $ 9 9	 . 
 !1245.'*uDNDL
 ) !!5!5doot}}!UVDN*84DL(    returnc                     t         S )zLists the supported models.

        Returns:
            list[SparseModelDescription]: A list of SparseModelDescription objects containing the model information.
        )r2   clss    rT   _list_supported_modelszBm25._list_supported_models   s
     %$rU   	model_dirc                     || dz  }|j                         sg S t        |d      5 }|j                         j                         cd d d        S # 1 sw Y   y xY w)Nr(   r)existsopenread
splitlines)rY   r[   r:   stopwords_pathfs        rT   rO   zBm25._load_stopwords   sN    "z%66$$&I.#&!668&&( '&&s   AA	documents
batch_sizeparallelr@   c              #   Z  K   d}t        |t              r|g}d}t        |t              rt        |      |k  rd}||r+t	        ||      D ]  }	| j                  |	      E d {     y |dk(  rt        j                         }dt               v rdnd}
||| j                  | j                  | j                  | j                  | j                  | j                  ||d
}t        |xs d| j!                         |
      } |j"                  t	        ||      fi |D ]  }	|	D ]  }|   y 7 ǭw)	NFTr   
forkserverspawn)
r5   r6   r7   r8   r9   r:   r;   r<   r@   r=      )num_workersworkerstart_method)
isinstancerF   listlenr   	raw_embedos	cpu_countr   r7   r8   r9   r:   r;   r<   r   _get_worker_classordered_map)rQ   r5   r6   rd   re   rf   r@   r=   is_smallbatchrm   paramspoolrecords                 rT   _embed_documentszBm25._embed_documents   s-     i%"IHi&9~
*x#Iz:>>%000 ; 1}<<>+7;P;R+R<X_L(&VVVV<< MM$($9$9#'#7#7$4':F &$M--/)D
 *))*Y
*KVvV#F L $ W/ 1s   AD+!D)"CD+c           	   +      K   | j                  | j                  t        | j                        |||| j                  | j
                        E d{    y7 w)a  
        Encode a list of documents into list of embeddings.
        We use mean pooling with attention so that the model can handle variable-length inputs.

        Args:
            documents: Iterator of documents or single document to embed
            batch_size: Batch size for encoding -- higher values will use more memory, but be faster
            parallel:
                If > 1, data-parallel encoding will be used, recommended for offline encoding of large datasets.
                If 0, use all available cores.
                If None, don't use data-parallel processing, use default onnxruntime threading instead.

        Returns:
            List of embeddings, one per document
        )r5   r6   rd   re   rf   r@   r=   N)r{   r5   rF   r6   rI   rG   )rQ   rd   re   rf   r>   s        rT   embedz
Bm25.embed   sS     , (($..)!!33 $ 9 9 ) 
 	
 	
s   AAAAtokensc                     g }|D ]  }|j                         }|| j                  v r"|| j                  v r1t        |      | j                  kD  rJ| j
                  r| j
                  j                  |      n|}|sv|j                  |        |S N)lowerrL   rM   rp   r;   rN   	stem_wordappend)rQ   r~   stemmed_tokenstokenlower_tokenstemmed_tokens         rT   _stemz
Bm25._stem   s    $&E++-K(((dnn,5zD111CG<<DLL22;?U`M%%m4   rU   c                     g }|D ]n  }t        |      }| j                  j                  |      }| j                  |      }| j	                  |      }|j                  t        j                  |             p |S r   )r   rP   tokenizer   _term_frequencyr   r   	from_dict)rQ   rd   
embeddingsdocumentr~   r   token_id2values          rT   rq   zBm25.raw_embed  sp     -/
!H.x8H^^,,X6F!ZZ/N!11.ANo77GH " rU   textsc                     d}t        |t              r|gn|}|D ]6  }t        |      }| j                  j	                  |      }|t        |      z  }8 |S )Nr   )rn   rF   r   rP   r   rp   )rQ   r   r>   	token_numtextr   r~   s          rT   token_countzBm25.token_count  sW    	%eS1uD.t4H^^,,X6FV$I  rU   c           	      X   i }t        t              }|D ]  }||xx   dz  cc<    t        |      }|D ]t  }| j                  |      }||   }|| j                  dz   z  ||<   ||xx   || j                  d| j
                  z
  | j
                  |z  | j                  z  z   z  z   z  cc<   v |S )ag  Calculate the term frequency part of the BM25 formula.

        (
            f(q_i, d) * (k + 1)
        ) / (
            f(q_i, d) + k * (1 - b + b * (|d| / avg_len))
        )

        Args:
            tokens (list[str]): The list of tokens in the document.

        Returns:
            dict[int, float]: The token_id to term frequency mapping.
        rj   )r   intrp   compute_token_idr7   r8   r9   )rQ   r~   tf_mapcounterr   doc_lentoken_idnum_occurrencess           rT   r   zBm25._term_frequency  s     $&)4S)9#MM"a'" $ f+$M,,];H%m4O.$&&1*=F88$&&DFF
TVVg-<<3 ! 	 % rU   r   c                 >    t        t        j                  |            S r   )absmmh3hash)rY   r   s     rT   r   zBm25.compute_token_id6  s    499U#$$rU   queryc           	   +   x   K   t        |t              r|g}|D ]  }t        |      } j                  j	                  |      } j                  |      }t        j                  t        t         fd|D                    t        j                        }t        j                  |      }t        ||        yw)zTo emulate BM25 behaviour, we don't need to use weights in the query, and
        it's enough to just hash the tokens and assign a weight of 1.0 to them.
        c              3   @   K   | ]  }j                  |        y wr   )r   ).0r   rQ   s     rT   	<genexpr>z#Bm25.query_embed.<locals>.<genexpr>F  s     R>%..u5>s   )dtype)indicesvaluesN)rn   rF   r   rP   r   r   nparrayro   rK   int32	ones_liker   )rQ   r   r>   r   r~   r   	token_idsr   s   `       rT   query_embedzBm25.query_embed:  s      eS!GED*40D^^,,T2F!ZZ/NSR>RRShhI \\),F!)FCC s   B7B:
Bm25Workerc                     t         S r   )r   rX   s    rT   rt   zBm25._get_worker_classL  s    rU   )Ng333333?g      ?g      p@r   (   FN)   NFN)r   N)__name__
__module____qualname____doc__rF   floatr   boolr   rB   classmethodro   r   rZ   r   rO   r   r   r{   r}   r   rq   r   dictr   r   r   r   rt   __classcell__)rS   s   @rT   r4   r4   =   s   @ !%! " %*..).) :.) 	.)
 .) .) .) .) .) !4Z.) .)` %t,B'C % % ) ) )S	 ) ) #!&*./!/! /! #&	/!
 /! */! /! !4Z/! 
/	"/!h #	
#&
 
 *	

 
 
/	"
@DI $s) (9 
o	x}!4   d3i De4D < %S %S % %Dx}!4 D DQ`Ha D$ $|"4  rU   r4   c            	           e Zd ZdededefdZededededd fd       Zdee	e
ef      dee	e
ee   f      fdZededededefd	       Zy
)r   r5   r6   r>   c                 6     | j                   ||fi || _        y r   )init_embeddingr)   )rQ   r5   r6   r>   s       rT   rB   zBm25Worker.__init__R  s     )T((YI&I
rU   rV   c                      | d||d|S N)r5   r6    r   )rY   r5   r6   r>   s       rT   startzBm25Worker.startZ  s    HjIHHHrU   itemsc              #   b   K   |D ]&  \  }}| j                   j                  |      }||f ( y wr   )r)   rq   )rQ   r   idxrw   onnx_outputs        rT   processzBm25Worker.process^  s5       JC**..u5K{""  s   -/c                     t        d| |d|S r   )r4   )r5   r6   r>   s      rT   r   zBm25Worker.init_embeddinge  s    IzYI&IIrU   N)r   r   r   rF   r   rB   r   r   r   tupler   ro   r   r   staticmethodr4   r   r   rU   rT   r   r   Q  s    JJ J 	J Is Is Ic Il I I#eCHo.#	%T/223	4# J3 J3 J# J$ J JrU   r   )&rr   collectionsr   multiprocessingr   pathlibr   typingr   r   r   r   numpyr   py_rust_stemmersr	   fastembed.common.utilsr
   r   r   r   fastembed.parallel_processorr   r   &fastembed.sparse.sparse_embedding_baser   r    fastembed.sparse.utils.tokenizerr   "fastembed.common.model_descriptionr   r   rC   r2   ro   __annotations__r4   r   )langs   0rT   <module>r      s    	 # 1  & &   ,  D = R , L}-4GH4GDTF$-4GH
7 t23 Q" QhJ Jw Is   1B'