
    ^Nj:;                        d dl Zd dlmZ d dlmZ d dlmZ eez  ZdZ	 ej                   ed      D  cg c]  }  e|       j                  d       c} ej                        Zd	ej                   d
ej                   fdZ G d d      Z G d d      Zedk(  rBej*                  j-                  ddd      Z eddddd      ZeD ]  Zej5                  e        yyc c} w )    N)
NumpyArray) LateInteractionTextEmbeddingBase)&LateInteractionMultimodalEmbeddingBaseA      1)dtypeidsreturnc                     t        |       }t        j                  | dddf   | dddf         }|j                  t        j                        j                  ||d      }t        |   j                  d      S )zCompute full Hamming distance matrix

    Args:
    ids: shape (n,) - array of ids, only size of the array matters

    Return:
        np.ndarray (n, n) - hamming distance matrix
    N      axis)lennpbitwise_xorviewuint8reshapePOPCOUNT_LUTsum)r
   nxor_vals
bytes_views       m/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/fastembed/postprocess/muvera.pyhamming_distance_matrixr      sg     	CA~~c!T'lCaL9Hrxx(00Aq9J
#''Q'//    c                       e Zd ZdZdededej                  j                  fdZdej                  dej                  fdZ
y	)
SimHashProjectiona  
    SimHash projection component for MUVERA clustering.

    This class implements locality-sensitive hashing using random hyperplanes
    to partition the vector space into 2^k_sim clusters. Each vector is assigned
    to a cluster based on which side of k_sim random hyperplanes it falls on.

    Attributes:
        k_sim (int): Number of SimHash functions (hyperplanes)
        dim (int): Dimensionality of input vectors
        simhash_vectors (np.ndarray): Random hyperplane normal vectors of shape (dim, k_sim)
    k_simdimrandom_generatorc                 R    || _         || _        |j                  ||f      | _        y)a@  
        Initialize SimHash projection with random hyperplanes.

        Args:
            k_sim (int): Number of SimHash functions, determines 2^k_sim clusters
            dim (int): Dimensionality of input vectors
            random_generator (np.random.Generator): Random number generator for reproducibility
        sizeN)r!   r"   normalsimhash_vectors)selfr!   r"   r#   s       r   __init__zSimHashProjection.__init__.   s,     
/66S%L6Ir   vectorsr   c                 t    || j                   z  }|dkD  dt        j                  | j                        z  z  }|S )a$  
        Compute the cluster IDs for a given vector using SimHash.

        The cluster ID is determined by computing the dot product of the vector
        with each hyperplane normal vector, taking the sign, and interpreting
        the resulting binary string as an integer.

        Args:
            vectors (np.ndarray): Input vectors of shape (n, dim,)

        Returns:
            np.ndarray: Cluster IDs in range [0, 2^k_sim - 1]

        Raises:
            AssertionError: If a vector shape doesn't match expected dimensionality
        r      )r(   r   aranger!   )r)   r+   dot_productcluster_idss       r   get_cluster_idsz!SimHashProjection.get_cluster_ids<   s?    $ d*** 	 #Q1		$**0E+EFr   N)__name__
__module____qualname____doc__intr   random	Generatorr*   ndarrayr1    r   r   r    r        sJ    Jc J Jryy?R?R Jrzz bjj r   r    c                       e Zd ZdZ	 	 	 	 ddededededef
dZe	 	 	 	 ddededededed	d fd
       Zd	efdZ	e
d	efd       Zded	efdZded	efdZ	 	 ddededed	efdZy)Muveraa  
    MUVERA (Multi-Vector Retrieval Architecture) algorithm implementation.

    This class creates Fixed Dimensional Encodings (FDEs) from variable-length
    sequences of vectors by using SimHash clustering and random projections.
    The process involves:
    1. Clustering vectors using multiple SimHash projections
    2. Computing cluster centers (with different strategies for docs vs queries)
    3. Applying random projections for dimensionality reduction
    4. Concatenating results from all projections

    Attributes:
        k_sim (int): Number of SimHash functions per projection
        dim (int): Input vector dimensionality
        dim_proj (int): Output dimensionality after random projection
        r_reps (int): Number of random projection repetitions
        random_seed (int): Random seed for consistent random matrix generation
        simhash_projections (List[SimHashProjection]): SimHash instances for clustering
        dim_reduction_projections (np.ndarray): Random projection matrices of shape (R_reps, d, d_proj)
    r"   r!   dim_projr_repsrandom_seedc                 h   ||kD  rt        d| d| d      || _        || _        || _        || _        t
        j                  j                  |      }t        |      D cg c]$  }t        | j                  | j                  |      & c}| _
        |j                  ddg|||f      | _        yc c}w )	aQ  
        Initialize MUVERA algorithm with specified parameters.

        Args:
            dim (int): Dimensionality of individual input vectors
            k_sim (int, optional): Number of SimHash functions (creates 2^k_sim clusters).
                                   Defaults to 5.
            dim_proj (int, optional): Dimensionality after random projection (must be <= dim).
                                    Defaults to 16.
            r_reps (int, optional): Number of random projection repetitions for robustness.
                                    Defaults to 20.
            random_seed (int, optional): Seed for random number generator to ensure
                                         reproducible results. Defaults to 42.

        Raises:
            ValueError: If dim_proj > dim (cannot project to higher dimensionality)
        z4Cannot project to a higher dimensionality (dim_proj=z > dim=))r!   r"   r#   r-   r%   N)
ValueErrorr!   r"   r=   r>   r   r7   default_rngranger    simhash_projectionschoicedim_reduction_projections)r)   r"   r!   r=   r>   r?   	generator_s           r   r*   zMuvera.__init__j   s    2 c>FxjPWX[W\\]^  
 II))+6	 6]$
" DJJDHHyY"$
 
 *3)9)92q'QTV^H_)9)`&$
s    )B/modelr   c                 0     | |j                   ||||      S )a  
        Create a Muvera instance from a multi-vector embedding model.

        This class method provides a convenient way to initialize a MUVERA
        that is compatible with a given multi-vector model by automatically extracting
        the embedding dimensionality from the model.

        Args:
            model (MultiVectorModel): A late interaction text or multimodal embedding model
                                    that provides multi-vector embeddings. Must have an
                                    `embedding_size` attribute specifying the dimensionality
                                    of individual vectors.
            k_sim (int, optional): Number of SimHash functions (creates 2^k_sim clusters).
                                   Defaults to 5.
            dim_proj (int, optional): Dimensionality after random projection (must be <= model's
                                    embedding_size). Defaults to 16.
            r_reps (int, optional): Number of random projection repetitions for robustness.
                                    Defaults to 20.
            random_seed (int, optional): Seed for random number generator to ensure
                                         reproducible results. Defaults to 42.

        Returns:
            Muvera: A configured MUVERA instance ready to process embeddings from the given model.

        Raises:
            ValueError: If dim_proj > model.embedding_size (cannot project to higher dimensionality)

        Example:
            >>> from fastembed import LateInteractionTextEmbedding
            >>> model = LateInteractionTextEmbedding(model_name="colbert-ir/colbertv2.0")
            >>> muvera = Muvera.from_multivector_model(
            ...     model=model,
            ...     k_sim=6,
            ...     dim_proj=32
            ... )
            >>> # Now use postprocessor with embeddings from the model
            >>> embeddings = np.array(list(model.embed(["sample text"])))
            >>> fde = muvera.process_document(embeddings[0])
        )r"   r!   r=   r>   r?   )embedding_size)clsrK   r!   r=   r>   r?   s         r   from_multivector_modelzMuvera.from_multivector_model   s'    ` $$#
 	
r   c                 X    d| j                   z  }| j                  |z  | j                  z  S )z
        Get the output dimension of the MUVERA algorithm.

        Returns:
            int: Output dimension (r_reps * num_partitions * dim_proj) where b = 2^k_sim
        r   )r!   r>   r=   )r)   num_partitionss     r   _get_output_dimensionzMuvera._get_output_dimension   s)     DJJ{{^+dmm;;r   c                 "    | j                         S )N)rR   )r)   s    r   rM   zMuvera.embedding_size   s    ))++r   r+   c                 *    | j                  |dd      S )a  
        Encode a document's vectors into a Fixed Dimensional Encoding (FDE).

        Uses document-specific settings: normalizes cluster centers by vector count
        and fills empty clusters using Hamming distance-based selection.

        Args:
            vectors (NumpyArray): Document vectors of shape (n_tokens, dim)

        Returns:
            NumpyArray: Fixed dimensional encodings of shape (r_reps * b * dim_proj,)
        Tfill_empty_clustersnormalize_by_countprocessr)   r+   s     r   process_documentzMuvera.process_document   s     ||GRV|WWr   c                 *    | j                  |dd      S )a  
        Encode a query's vectors into a Fixed Dimensional Encoding (FDE).

        Uses query-specific settings: no normalization by count and no empty
        cluster filling to preserve query vector magnitudes.

        Args:
            vectors (NumpyArray]): Query vectors of shape (n_tokens, dim)

        Returns:
            NumpyArray: Fixed dimensional encoding of shape (r_reps * b * dim_proj,)
        FrU   rX   rZ   s     r   process_queryzMuvera.process_query   s     ||GSX|YYr   rV   rW   c           	      :   |j                   d   | j                  k(  s!J d| j                   d|j                           g }d| j                  z  }t        j                  |      }|rt        |      nd}t        | j                        D ]  \  }}	t        j                  || j                  f      }
|D ci c]  }|g  }}d}d}|	j                  |      }t        |t        |            D ])  \  }\  }}|
|xx   |z  cc<   ||   j                  |       + |s|rt        j                  ||      }|dk(  }|r"|J |J | }|
|xx   ||   dddf   z  cc<   |r|J |J t        j                  |dddf   t        |      }t        j                  |d      }t        j                   ||   D cg c]  }|||   d       c}      j#                  d	| j                        }||
|<   | j$                  | j                  k  rX| j&                  |   }dt        j(                  | j$                        z  |
|z  z  }|j                  |j+                                |j                  |
j+                                 t        j,                  |      S c c}w c c}w )
a  
        Core encoding method that transforms variable-length vector sequences into FDEs.

        The encoding process:
        1. For each of r_reps random projections:
           a. Assign vectors to clusters using SimHash
           b. Compute cluster centers (sum of vectors in each cluster)
           c. Optionally normalize by cluster size
           d. Fill empty clusters using Hamming distance if requested
           e. Apply random projection for dimensionality reduction
           f. Flatten cluster centers into a vector
        2. Concatenate all projection results

        Args:
            vectors (np.ndarray): Input vectors of shape (n_vectors, dim)
            fill_empty_clusters (bool): Whether to fill empty clusters using nearest
                                      vectors based on Hamming distance of cluster IDs
            normalize_by_count (bool): Whether to normalize cluster centers by the
                                     number of vectors assigned to each cluster

        Returns:
            np.ndarray: Fixed dimensional encoding of shape (r_reps * b * dim_proj)
                        where B = 2^k_sim is the number of clusters

        Raises:
            AssertionError: If input vectors don't have expected dimensionality
        r-   zExpected vectors of shape (n, z), got r   N)	minlengthr   r   rB   )shaper"   r!   r   r.   r   	enumeraterF   zerosr1   zipappendbincountwhereMAX_HAMMING_DISTANCEargminarrayr   r=   rH   sqrtflattenconcatenate)r)   r+   rV   rW   output_vectorsrQ   cluster_center_idsprecomputed_hamming_matrixprojection_indexsimhashcluster_centerscluster_center_idcluster_center_id_to_vectorscluster_vector_counts
empty_maskvector_cluster_ids
cluster_idvec_idxvecnon_empty_maskmasked_hammingnearest_non_emptyfill_vectorsdim_reduction_projectionprojected_centerss                            r   rY   zMuvera.process   s   D MM!(	M+DHH:WW]]OL	M(  DJJYY~6;N#$67TX 	# *343K3K)L%g hh'ABO?QB?Q*;!2%?Q ) B %)!J ")!8!8!A.12DiPWFX.Y*
NWc
+s2+,Z8??H /Z "%8(*4FR`(a%2a7
!!---,888",/3H3XYZ\`Y`3aa/ #!---1===!#tQw')=?Y" %'IIn1$E!!xx +<J*G*GJ   <Z H KL*G 
 '"dhh'  /;
+ }}txx'+/+I+I$,( &')?%?#&>>%!
 %%&7&?&?&AB !!/"9"9";<o *Mt ~~n--oB>s   4
J3J
N)         *   )TT)r2   r3   r4   r5   r6   r*   classmethodMultiVectorModelrO   rR   propertyrM   r   r[   r]   boolrY   r:   r   r   r<   r<   T   s9   0 )a)a )a 	)a
 )a )aV  5
5
 5
 	5

 5
 5
 
5
 5
n<s < , , ,X
 Xz XZZ ZJ Z$ %)#'	i.i. "i. !	i.
 
i.r   r<   __main__
   d         r   r   r   )numpyr   fastembed.common.typesr   :fastembed.late_interaction.late_interaction_embedding_baser   Pfastembed.late_interaction_multimodal.late_interaction_multimodal_embedding_baser   r   rg   ri   rE   bincountr   r   r9   r   r    r<   r2   r7   randnv_arrsmuverav_arrrY   )xs   0r   <module>r      s     -
 46\\  rxxE#J?JqQc*J?rxxP0 0

 01 1hN. N.b zYY__Rc*FCAr2&Fu 	 o
 @s   C