
    Nga)                     P   d Z 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mZmZmZmZmZmZ ddlmZmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZmZ ddlm Z m!Z! ddl"m#Z#  ed          Z$ ede          Z%dee$         de
e$ge%f         dee$         fdZ& G d de          Z'dS )zo
Ensemble retriever that ensemble the results of
multiple retrievers by using weighted  Reciprocal Rank Fusion
    N)defaultdict)Hashable)chain)	AnyCallableDictIterableIteratorListOptionalTypeVarcast)#AsyncCallbackManagerForRetrieverRunCallbackManagerForRetrieverRun)Document)BaseRetrieverRetrieverLike)RunnableConfig)ensure_configpatch_config)ConfigurableFieldSpecget_unique_config_specs)model_validatorTH)bounditerablekeyreturnc              #      K   t                      }| D ]*} ||          x}|vr|                    |           |V  +dS )a  Yield unique elements of an iterable based on a key function.

    Args:
        iterable: The iterable to filter.
        key: A function that returns a hashable key for each element.

    Yields:
        Unique elements of the iterable based on the key function.
    N)setadd)r   r   seeneks        Y/var/www/html/ai-engine/env/lib/python3.11/site-packages/langchain/retrievers/ensemble.pyunique_by_keyr'   (   sZ       55D  QKA$$HHQKKKGGG     c            
       ,   e Zd ZU dZee         ed<   ee         ed<   dZe	ed<   dZ
ee         ed<   edee         fd	            Z ed
          edeeef         defd                        Z	 ddedee         dedee         fdZ	 ddedee         dedee         fdZdededee         fdZdededee         fdZdddededee         dee         fdZdddededee         dee         fdZdeee                  dee         fdZdS )EnsembleRetrieverae  Retriever that ensembles the multiple retrievers.

    It uses a rank fusion.

    Args:
        retrievers: A list of retrievers to ensemble.
        weights: A list of weights corresponding to the retrievers. Defaults to equal
            weighting for all retrievers.
        c: A constant added to the rank, controlling the balance between the importance
            of high-ranked items and the consideration given to lower-ranked items.
            Default is 60.
        id_key: The key in the document's metadata used to determine unique documents.
            If not specified, page_content is used.
    
retrieversweights<   cNid_keyr   c                 >    t          d | j        D                       S )z+List configurable fields for this runnable.c              3   .   K   | ]}|j         D ]}|V  d S N)config_specs).0	retrieverspecs      r&   	<genexpr>z1EnsembleRetriever.config_specs.<locals>.<genexpr>Q   sJ       '
 '
i>T'
 '
6:D'
 '
 '
 '
 '
 '
 '
r(   )r   r+   )selfs    r&   r3   zEnsembleRetriever.config_specsN   s4     ' '
 '
"&/'
 '
 '
 
 
 	
r(   before)modevaluesc                 r    |                     d          s!t          |d                   }d|z  g|z  |d<   |S )Nr,   r+      )getlen)clsr;   n_retrieverss      r&   set_weightszEnsembleRetriever.set_weightsU   sG     zz)$$ 	Bvl344L!"\!1 2\ AF9r(   inputconfigkwargsc                 *   ddl m} t          |          }|                    |                    d          d |                    dd          |                    dg           | j        |                    di           | j                  } |j        d |fd	|                    d
          p|                                 i|}	 | 	                    |||          } |j
        |fi | |S # t          $ r}|                    |           |d }~ww xY w)Nr   )CallbackManager	callbacksverboseFtagsmetadatarI   inheritable_tags
local_tagsinheritable_metadatalocal_metadatanamerun_namerun_managerrD   )langchain_core.callbacksrG   r   	configurer>   rJ   rK   on_retriever_startget_namerank_fusionon_retriever_end	Exceptionon_retriever_error)	r8   rC   rD   rE   rG   callback_managerrT   resultr$   s	            r&   invokezEnsembleRetriever.invoke]   se    	=<<<<<v&&*44JJ{##JJy%00#ZZ33y!'J!;!;= 5 
 
 :&9
 
 J'':4==??
 	
 

	%%eV%TTF
 )K(    M  	 	 	**1---G	s   C, ,
D6DDc                 ^  K   ddl m} t          |          }|                    |                    d          d |                    dd          |                    dg           | j        |                    di           | j                  } |j        d |fd	|                    d
          p|                                 i| d {V }	 | 	                    |||           d {V } |j
        |fi | d {V  |S # t          $ r"}|                    |           d {V  |d }~ww xY w)Nr   )AsyncCallbackManagerrH   rI   FrJ   rK   rL   rQ   rR   rS   )rU   ra   r   rV   r>   rJ   rK   rW   rX   arank_fusionrZ   r[   r\   )	r8   rC   rD   rE   ra   r]   rT   r^   r$   s	            r&   ainvokezEnsembleRetriever.ainvoke~   s      	BAAAAAv&&/99JJ{##JJy%00#ZZ33y!'J!;!;= : 
 
 @,?
 
 J'':4==??
 	
 
 
 
 
 
 
 
	,,;v -        F /+.          M  	 	 	00333333333G	s   D   
D,
D''D,queryrT   c                2    |                      ||          }|S )z
        Get the relevant documents for a given query.

        Args:
            query: The query to search for.

        Returns:
            A list of reranked documents.
        )rY   r8   rd   rT   fused_documentss       r&   _get_relevant_documentsz)EnsembleRetriever._get_relevant_documents   s    " **5+>>r(   c                B   K   |                      ||           d{V }|S )z
        Asynchronously get the relevant documents for a given query.

        Args:
            query: The query to search for.

        Returns:
            A list of reranked documents.
        N)rb   rf   s       r&   _aget_relevant_documentsz*EnsembleRetriever._aget_relevant_documents   s5      " !% 1 1% E EEEEEEEr(   )rD   c                    fdt          | j                  D             }t          t          |                    D ]}d ||         D             ||<   |                     |          }|S )z
        Retrieve the results of the retrievers and use rank_fusion_func to get
        the final result.

        Args:
            query: The query to search for.

        Returns:
            A list of reranked documents.
        c                     g | ]D\  }}|                     t                              d |dz                                  ES 
retriever_r=   )tag)rH   )r_   r   	get_childr4   ir5   rD   rd   rT   s      r&   
<listcomp>z1EnsembleRetriever.rank_fusion.<locals>.<listcomp>   sw     
 
 
 9 k&;&;@RQqS@R@R&;&S&S   
 
 
r(   c                     g | ]<}t          |t                    r#t          t          t          |                     n|=S )page_content)
isinstancestrr   r   r4   docs     r&   rs   z1EnsembleRetriever.rank_fusion.<locals>.<listcomp>   sQ     ! ! ! :DC9M9MVd3nn5555SV! ! !r(   )	enumerater+   ranger?   weighted_reciprocal_rankr8   rd   rT   rD   retriever_docsrr   rg   s    ```   r&   rY   zEnsembleRetriever.rank_fusion   s    &
 
 
 
 
 
 !*$/ : :
 
 
 s>**++ 	 	A! !)!,! ! !N1 77GGr(   c                
  K   t          j        fdt          | j                  D               d{V }t	          t          |                    D ]}d ||         D             ||<   |                     |          }|S )z
        Asynchronously retrieve the results of the retrievers
        and use rank_fusion_func to get the final result.

        Args:
            query: The query to search for.

        Returns:
            A list of reranked documents.
        c                     g | ]D\  }}|                     t                              d |dz                                  ES rm   )rc   r   rp   rq   s      r&   rs   z2EnsembleRetriever.arank_fusion.<locals>.<listcomp>  sz        !Ay !! +*?*?DVQRSTQTDVDV*?*W*W     r(   Nc                 \    g | ])}t          |t                    st          |           n|*S ru   )rw   r   ry   s     r&   rs   z2EnsembleRetriever.arank_fusion.<locals>.<listcomp>  sH     ! ! ! 3=S(2K2KTc****QT! ! !r(   )asynciogatherr{   r+   r|   r?   r}   r~   s    ```   r&   rb   zEnsembleRetriever.arank_fusion   s      &  '~      %.do$>$>  
 
 

 

 

 

 

 

 s>**++ 	 	A! !)!,! ! !N1 77GGr(   	doc_listsc                     t          |          t           j                  k    rt          d          t          t                    t          | j                  D ]U\  }}t          |d          D ]>\  }} j        |j        n|j	         j                 xx         || j
        z   z  z  cc<   ?Vt          j        |          }t          t          | fd          d fd          }|S )	a  
        Perform weighted Reciprocal Rank Fusion on multiple rank lists.
        You can find more details about RRF here:
        https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf

        Args:
            doc_lists: A list of rank lists, where each rank list contains unique items.

        Returns:
            list: The final aggregated list of items sorted by their weighted RRF
                    scores in descending order.
        z<Number of rank lists must be equal to the number of weights.r=   )startNc                 D    j         | j        n| j        j                  S r2   r/   rv   rK   )rz   r8   s    r&   <lambda>z<EnsembleRetriever.weighted_reciprocal_rank.<locals>.<lambda>E  s'    {* $$dk2 r(   Tc                 P    j         | j        n| j        j                           S r2   r   )rz   	rrf_scorer8   s    r&   r   z<EnsembleRetriever.weighted_reciprocal_rank.<locals>.<lambda>L  s'    I$(K$7  S\$+=V r(   )reverser   )r?   r,   
ValueErrorr   floatzipr{   r/   rv   rK   r.   r   from_iterablesortedr'   )	r8   r   doc_listweightrankrz   all_docssorted_docsr   s	   `       @r&   r}   z*EnsembleRetriever.weighted_reciprocal_rank  sV    y>>S....N   '2%&8&8	 #It| < < 	. 	.Hf&xq999 . .	c  ;. (( \$+6	   tdf}-.    . &y11         
 
 
 r(   r2   ) __name__
__module____qualname____doc__r   r   __annotations__r   r.   intr/   r   rx   propertyr   r3   r   classmethodr   r   rB   r   r   r_   rc   r   rh   r   rj   rY   rb   r}    r(   r&   r*   r*   9   s          ]####%[AsKKK FHSM   
d#89 
 
 
 X
 _(###c3h C    [ $# >B "*>":MP	h   D >B! !!"*>":!MP!	h! ! ! !F 4	
 
h   * 9	
 
h   4 ,0' ' '' 4'
 (' 
h' ' ' '\ ,0) ) )) 9)
 () 
h) ) ) )V1d8n-1	h1 1 1 1 1 1r(   r*   )(r   r   collectionsr   collections.abcr   	itertoolsr   typingr   r   r   r	   r
   r   r   r   r   rU   r   r   langchain_core.documentsr   langchain_core.retrieversr   r   langchain_core.runnablesr   langchain_core.runnables.configr   r   langchain_core.runnables.utilsr   r   pydanticr   r   r   r'   r*   r   r(   r&   <module>r      s   
  # # # # # # $ $ $ $ $ $      
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
        . - - - - - B B B B B B B B 3 3 3 3 3 3 G G G G G G G G        % $ $ $ $ $GCLLGCx   HQK hsAv.> 8A;    "W W W W W W W W W Wr(   