o
    CibI                     @   s   d dl Z d dlZd dlZd dlmZ d dlZd dlZd dlZd dl	m
Z
 dddZdddZddd	Zd
d ZG dd dZG dd dZdejejd d ddd dddd ddfddZdS )    N)
ThreadPool)get_invlistc                 C   s~   |j \}}|j |fksJ t| tjr|d9 }|| jksJ |dur/|j |fks*J t|}| |t||t| dS )zP
    Add elements to an IVF index, where the assignment is already computed
       N)shape
isinstancefaissIndexBinaryIVFdswig_ptradd_core)	index_ivfxaidsnr	    r   o/var/www/html/fyndo/python/python_agents/rag_suite/venv/lib/python3.10/site-packages/faiss/contrib/ivf_tools.pyadd_preassigned   s   

r   c                 C   s   |j \}}t| tjr|d9 }d}nd}|| jksJ |j || jfks%J |du r4tj|| jf|d}n
|j || jfks>J | ||||S )z
    Perform a search in the IVF index, with predefined lists to search into.
    Supports indexes with pretransforms (as opposed to the
    IndexIVF.search_preassigned, that cannot be applied with pretransform).
    r   int32float32Ndtype)	r   r   r   r   r	   nprobenpzerossearch_preassigned)r   xqklist_nos
coarse_disr   r	   dis_typer   r   r   r   #   s   
r   c                 C   s   |j \}}t| tjr|d9 }d}nd}|du r#tj|| jf|d}n
|j || jfks-J || jks4J |j || jfks>J t|}tj	}	| 
||	|||	||	|| t|j|d  }
t|
d }t|j| }t|j| }|
||fS )z[
    Perform a range search in the IVF index, with predefined lists to
    search into
    r   r   r   Nr      )r   r   r   r   r   emptyr   r	   RangeSearchResultr
   range_search_preassignedrev_swig_ptrlimscopyint	distanceslabels)r   r   radiusr   r   r   r	   r    resspr'   num_resultsdistindicesr   r   r   r%   =   s,   



r%   c                 C   s   |j dkr| j }|| || n|j | jksJ | j}d| _t| j}|j	
| || _t| dr?| j| |S |g| _|S )zQ replace the IVF quantizer with a flat quantizer and return the
    old quantizerr   Freferenced_objects)ntotal	quantizerreconstruct_ntrainaddnlist
own_fieldsr   downcast_indexthisownhasattrr2   append)r   new_quantizer	centroidsold_ownold_quantizerr   r   r   replace_ivf_quantizerc   s   



rC   c                   @   s~   e Zd ZdZ		dddZdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd ZdS ) BigBatchSearcherz
    Object that manages all the data related to the computation
    except the actual within-bucket matching and the organization of the
    computation (parallel or not)
    r   Fc                 C   s`   || _ g | _|| _|| _|| _t|j}tjt	|||d| _
dgd | _t  | _| _d S )N)keep_maxr      )verbosetictocr   indexuse_float16r   is_similarity_metricmetric_type
ResultHeaplenrht_accutime	t_displayt0)selfrI   r   r   rG   rJ   rE   r   r   r   __init__   s   zBigBatchSearcher.__init__c                 C   s   t   | _d S N)rQ   	t_accu_t0rT   r   r   r   start_t_accu   s   zBigBatchSearcher.start_t_accuc                 C   s    | j |  t | j 7  < d S rV   )rP   rQ   rW   )rT   r   r   r   r   stop_t_accu   s    zBigBatchSearcher.stop_t_accuc                 C   s.   |t   f| _| jdkrt|ddd d S d S )Nr   Tendflush)rQ   rH   rG   print)rT   namer   r   r   tic   s   
zBigBatchSearcher.ticc                 C   s:   | j \}}t | }| jdkrt| d|dd |S )Nr   z: .3fz s)rH   rQ   rG   r_   )rT   r`   rS   dtr   r   r   toc   s
   

zBigBatchSearcher.tocc                 C   s   | j dks|dkrt | jd k rd S tdt | j dd| d| jj d| jd	 d
d| jd d
d| jd d
d| jd d
d| jd d
ddd t | _d S )Nr!   i  g      ?[z.1fz	 s] list /z times prep q r   rb   z prep b z comp    z res    z wait    r[   Tr\   )rG   rQ   rR   r_   rS   rI   r8   rP   )rT   lr   r   r   report   s$   
$




zBigBatchSearcher.reportc                 C   s   |  d d}t| j}tj|| jjfdd}td||D ] }t||| }| jj	
| j|| | jj\}}||||< q|   || _d S )Nzcoarse quantizationi   r   r   r   )ra   rN   r   r   r#   rI   r   rangeminr4   searchrd   q_assign)rT   bsnqro   i0i1q_dis_i
q_assign_ir   r   r   coarse_quantization   s   


z$BigBatchSearcher.coarse_quantizationc                 C   sz   |  d | j}|d7 }tj| j| jjd dd| _| j | _| j	dkr-t
d| jd  | jdd  | _| `|   d S )Nzbucket sortr!      )nbucketntr   z  number of -1s:)ra   ro   r   matrix_bucket_sort_inplacerI   r8   bucket_limsravel	query_idsrG   r_   rd   )rT   ro   r   r   r   reorder_assign   s   

zBigBatchSearcher.reorder_assignc                 C   s   t   }| j}| j| | j|d  }}| j|| }| j| }| jr+||j| }t   }t|j	|\}	}
| j
du rA|
 }
n| 
|
}
| jrS|
d}
|d}t   }| jd  || 7  < | jd  || 7  < |||	|
fS )z4 prepare the queries and database items for bucket lr!   Nfloat16r   )rQ   rI   r{   r}   r   by_residualr4   reconstructr   invlistsdecode_funcr|   rJ   astyperP   )rT   rj   rS   rI   rr   rs   q_subsetxq_lt1list_idsxb_lt2r   r   r   prepare_bucket   s&   





zBigBatchSearcher.prepare_bucketc                 C   sX   |du rdS t   }|du r|}n|| }| j||| | jd  t   | 7  < dS )z,add the bucket results to the heap structureNrh   )rQ   rO   add_result_subsetrP   )rT   r   Dr   IrS   r   r   r   add_results_to_heap   s   z$BigBatchSearcher.add_results_to_heapc                 C   s   | j j| jj| jjfS rV   )r   r   rI   r   r8   rX   r   r   r   sizes_in_checkpoint   s   z$BigBatchSearcher.sizes_in_checkpointc                 C   sD   |d }t |  || jj| jjfdt|dd t|| d S )Nz.tmp)sizescur_list_norO   wbr"   )	pickledumpr   rO   r   r   openosreplace)rT   fnamer   tmpnamer   r   r   write_checkpoint   s   
z!BigBatchSearcher.write_checkpointc                 C   s\   t t|d}|d |  ksJ |d d | jjd d < |d d | jjd d < |d S )Nrbr   rO   r   r!   r   )r   loadr   r   rO   r   r   )rT   r   ckpr   r   r   read_checkpoint  s
   z BigBatchSearcher.read_checkpointN)r   F)__name__
__module____qualname____doc__rU   rY   rZ   ra   rd   rk   rv   r~   r   r   r   r   r   r   r   r   r   rD   {   s"    	
rD   c                   @   s,   e Zd ZdZdejejfddZdd ZdS )BlockComputerz computation within one bucket knn_functionc                 C   s   || _ |jtjkrt|j|j}dd }d}nL|jtjkr;t|j|j	j
|j	j|j}|j	|_	|j	j}d|_|j}n)|jtjkr[t|j|jj|j}|j|_|jj}d|_|j}n	td|j d|| _|dkrmd n|| _|| _|| _|| _|| _d S )Nc                 S   s
   |  dS )Nr   )view)r   r   r   r   <lambda>  s   
 z(BlockComputer.__init__.<locals>.<lambda>FTzindex type z not supportedrI   )rI   	__class__r   IndexIVFFlat	IndexFlatr	   rL   
IndexIVFPQIndexPQpqMnbitsdecode
is_trainedr   IndexIVFScalarQuantizerIndexScalarQuantizersqqtypeRuntimeError
index_helpr   methodpairwise_distancesknn)rT   rI   r   r   r   r   r   r   r   r   r   rU     s8   
zBlockComputer.__init__c           	      K   s   | j j}|jdks|jdkrd  }}||fS | jdkr6t|| jj t|| j_	| j
||\}}||fS | jdkrI| j|||d}d }||fS | jdkr]| j|||fd|i|\}}||fS )Nr   rI   r   )metricr   r   )rI   rL   sizer   r   copy_array_to_vectorr   codesrN   r3   rn   r   r   )	rT   r   r   r   r   
extra_argsrL   r   r   r   r   r   block_search3  s    


zBlockComputer.block_searchN)	r   r   r   r   r   r   r   rU   r   r   r   r   r   r     s    
#r   r   Fr   @   r"   c           *         s  j }|dv s	J |j}t|| tdj }t| tdjtdj  }|| | }|dkrKtd| d| d| d	| d
|d dd t|||d t|||dj	 _	j
 _
|du rm   n| _   |du r{j}|dur||fdjfksJ tj|rtd|  |}td| ntd |dkrt||D ]3} |  |\}}}}t }|||\}} jd  t | 7  <  |||| qnP|dkrG fdd} |}d} td}!t||D ]=} | |!|| |d f}"|\}}}}   |||\}} d ||||f}    |" } d q j|   |!  n|| dksRJ dkrZt ntj |
dkrjt|
}# fdd}$t!" 	i 	fdd}%|$g |}&g } td}!d}'t||D ]z} | |&}(|!|$| | f}'   g } |
dkr|(D ]\}}}}|||\}}| #||||f qnt$|# |%|(}  d ||krdd     |' }& d |dur| | dkrtd|   %|| q| D ]}) j|)  q|!  dkr*  |
dkr3|#   &d  j'(   )   j'j* j'j+fS )a  
    Search queries xq in the IVF index, with a search function that collects
    batches of query vectors per inverted list. This can be faster than the
    regular search indexes.
    Supports IVFFlat, IVFPQ and IVFScalarQuantizer.

    Supports three computation methods:
    method = "index":
        build a flat index and populate it separately for each index
    method = "pairwise_distances":
        decompress codes and compute all pairwise distances for the queries
        and index and add result to heap
    method = "knn_function":
        decompress codes and compute knn results for the queries

    threaded=0: sequential execution
    threaded=1: prefetch next bucket while computing the current one
    threaded>1: prefetch this many buckets at a time.

    compute_threads>1: the knn function will get an additional thread_no that
        tells which worker should handle this.

    In threaded mode, the computation is tiled with the bucket perparation and
    the writeback of results (useful to maximize GPU utilization).

    use_float16: convert all matrices to float16 (faster for GPU gemm)

    q_assign: override coarse assignment, should be a matrix of size nq * nprobe

    checkpointing (only for threaded > 1):
    checkpoint: file where the checkpoints are stored
    checkpoint_freq: when to perform checkpoinging. Should be a multiple of threaded

    start_list, end_list: process only a subset of invlists
    )rI   r   r   r   int64r   r   zmemory: queries z assign z result z total z = i   @rb   z GiB)rG   rJ   )r   r   r   Nzrecovering checkpointz   start at listz$no checkpoint: starting from scratchrg   r!   c                    s*   | dur	 j |   |jk r |S dS )z` perform the addition for the previous bucket and
            prefetch the next (if applicable) N)r   r8   r   )to_addrj   )bbsrI   r   r   add_results_and_prefetch  s
   


z2big_batch_search.<locals>.add_results_and_prefetchri   c                    sf    fdd}dkr||  n || f}t|t| j}t j|}dkr1|  |S )Nc                    s    | D ]}|d ur j |  qd S rV   )r   )r   ta)r   r   r   add_results  s
   
zMbig_batch_search.<locals>.add_results_and_prefetch_batch.<locals>.add_resultsr   )apply_asyncrl   rm   r8   listr   get)r   rj   r   add_a
next_listsr-   )r   rI   	list_stepprefetch_mapprefetch_poolprefetch_threadsr   r   add_results_and_prefetch_batch  s   
z8big_batch_search.<locals>.add_results_and_prefetch_batchc                    s   | \}}}}zt   }W n% ty3    t}|t  < W d    n1 s,w   Y  Y nw  j||||d\}}||||fS )N)	thread_id)	threading	get_identKeyErrorrN   r   )bucketr   r   r   r   tidr   r   )compr   thread_id_to_seqthread_id_to_seq_lockr   r   do_comp  s   z!big_batch_search.<locals>.do_compzwriting checkpoint %szfinalize heap),r   nbytesrN   r   r   itemsizer_   rD   r   r   r   rv   ro   r~   r8   r   pathexistsr   rl   rk   r   rQ   r   rP   r   r   r   rY   rZ   r   closemapr   Lockr>   r   r   ra   rO   finalizerd   r   r   )*rI   r   r   r   r   r   rG   threadedrJ   r   computation_threadsro   
checkpointcheckpoint_freq
start_listend_listcrash_atr   mem_queries
mem_assignmem_resmem_totrj   r   r   r   r   t0ir   r   r   prefetched_bucketr   poolprefetched_bucket_a	comp_poolr   r   prefetched_bucketsprefetched_buckets_abucketsr   r   )
r   r   rI   r   r   r   r   r   r   r   r   big_batch_searchE  s   4

























r   rV   )rQ   r   r   multiprocessing.poolr   r   numpyr   r   faiss.contrib.inspect_toolsr   r   r   r%   rC   rD   r   r   r   r   r   r   r   r   <module>   s<   


& :