
    Ah#)                     *   S r SSKrSSKJr  SSKJrJrJr  SSKJ	r	  SSK
JrJrJrJrJr  SSKJrJr  SSKJr  SS	KJrJr  SS
KJr  SSKJrJr  SSKJrJr  SSK J!r!  SSK"J#r#  \" S5      r$\" S\S9r%S\\$   S\\$/\%4   S\\$   4S jr& " S S\5      r'g)zo
Ensemble retriever that ensemble the results of
multiple retrievers by using weighted  Reciprocal Rank Fusion
    N)defaultdict)HashableIterableIterator)chain)AnyCallableOptionalTypeVarcast)#AsyncCallbackManagerForRetrieverRunCallbackManagerForRetrieverRun)Document)BaseRetrieverRetrieverLike)RunnableConfig)ensure_configpatch_config)ConfigurableFieldSpecget_unique_config_specs)model_validator)overrideTH)bounditerablekeyreturnc              #   z   #    [        5       nU  H'  nU" U5      =oB;  d  M  UR                  U5        Uv   M)     g7f)zYield 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        U/var/www/html/shao/venv/lib/python3.13/site-packages/langchain/retrievers/ensemble.pyunique_by_keyr&   %   s6      5DQKA$HHQKG s   ;;c                      \ rS rSr% Sr\\   \S'   \\   \S'   Sr	\
\S'   Sr\\   \S'   \S	\\   4S
 j5       r\" SS9\S\\\4   S	\4S j5       5       r\ SS\S\\   S\S	\\   4S jj5       r\ SS\S\\   S\S	\\   4S jj5       rS\S\S	\\   4S jrS\S\S	\\   4S jrSS.S\S\S\\   S	\\   4S jjrSS.S\S\S\\   S	\\   4S jjr S\\\      S	\\   4S jr!Sr"g)EnsembleRetriever6   a9  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                 :    [        S U R                   5       5      $ )z+List configurable fields for this runnable.c              3   F   #    U H  oR                    H  o"v   M     M     g 7fN)config_specs).0	retrieverspecs      r%   	<genexpr>1EnsembleRetriever.config_specs.<locals>.<genexpr>N   s       '
"1Y>T>TdD>TD/s   !)r   r*   )selfs    r%   r2   EnsembleRetriever.config_specsK   s"     ' '
"&//'
 
 	
    before)modevaluesc                 f    UR                  S5      (       d  [        US   5      nSU-  /U-  US'   U$ )Nr+   r*      )getlen)clsr=   n_retrieverss      r%   set_weightsEnsembleRetriever.set_weightsR   s>     zz)$$vl34L!"\!1 2\ AF9r:   inputconfigkwargsc                     SSK Jn  [        U5      nUR                  UR	                  S5      S UR	                  SS5      UR	                  S/ 5      U R
                  UR	                  S0 5      U R                  S9nUR                  " S U4S	UR	                  S
5      =(       d    U R                  5       0UD6n U R                  XUS9nUR                  " U40 UD6  U$ ! [         a  nUR                  U5        e S nAff = f)Nr   )CallbackManager	callbacksverboseFtagsmetadatarL   inheritable_tags
local_tagsinheritable_metadatalocal_metadatanamerun_namerun_managerrG   )langchain_core.callbacksrJ   r   	configurer@   rM   rN   on_retriever_startget_namerank_fusionon_retriever_end	Exceptionon_retriever_error)	r8   rF   rG   rH   rJ   callback_managerrW   resultr#   s	            r%   invokeEnsembleRetriever.invokeZ   s    	=v&*44JJ{#JJy%0#ZZ3yy!'J!;== 5 
 '99
 J':4==?
 	

	%%eV%TF
 (( M  	**1-	s   7C 
C=&C88C=c                 X  #    SSK Jn  [        U5      nUR                  UR	                  S5      S UR	                  SS5      UR	                  S/ 5      U R
                  UR	                  S0 5      U R                  S9nUR                  " S U4S	UR	                  S
5      =(       d    U R                  5       0UD6I S h  vN n U R                  UUUS9I S h  vN nUR                  " U40 UD6I S h  vN   U$  N; N# N
! [         a   nUR                  U5      I S h  vN    e S nAff = f7f)Nr   )AsyncCallbackManagerrK   rL   FrM   rN   rO   rT   rU   rV   )rX   re   r   rY   r@   rM   rN   rZ   r[   arank_fusionr]   r^   r_   )	r8   rF   rG   rH   re   r`   rW   ra   r#   s	            r%   ainvokeEnsembleRetriever.ainvoke   sB     	Bv&/99JJ{#JJy%0#ZZ3yy!'J!;== : 
 -??
 J':4==?
 	
 
	,,' -  F ..   M)
	  	00333	sf   B9D*;C7<D*C= C9C= D*0C;1D*9C= ;D*=
D'D"DD""D''D*queryrW   c                $    U R                  X5      $ )z
Get the relevant documents for a given query.

Args:
    query: The query to search for.

Returns:
    A list of reranked documents.
)r\   r8   ri   rW   s      r%   _get_relevant_documents)EnsembleRetriever._get_relevant_documents   s    " 33r:   c                @   #    U R                  X5      I Sh  vN $  N7f)z
Asynchronously get the relevant documents for a given query.

Args:
    query: The query to search for.

Returns:
    A list of reranked documents.
N)rf   rk   s      r%   _aget_relevant_documents*EnsembleRetriever._aget_relevant_documents   s     " &&u::::s   )rG   c                   [        U R                  5       VVs/ sH2  u  pEUR                  U[        UUR	                  SUS-    3S9S95      PM4     nnn[        [        U5      5       HE  nXd    Vs/ sH1  n[        U[        5      (       a  [        [        [        U5      S9OUPM3     snXd'   MG     U R                  U5      $ s  snnf s  snf )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.

retriever_r?   tagrK   page_content)	enumerater*   rb   r   	get_childrangerA   
isinstancestrr   r   weighted_reciprocal_rankr8   ri   rW   rG   ir4   retriever_docsdocs           r%   r\   EnsembleRetriever.rank_fusion   s    6 !*$// :	
 !; )33*QUG8L3M !; 	 	
 s>*+A *,!,C :DC9M9Md3n5SVV,!N , ,,^<<'	
!s   8C17Cc                  #    [         R                  " [        U R                  5       VVs/ sH2  u  pEUR	                  U[        UUR                  SUS-    3S9S95      PM4     snn6 I Sh  vN n[        [        U5      5       H7  nXd    Vs/ sH#  n[        U[        5      (       d	  [        US9OUPM%     snXd'   M9     U R                  U5      $ s  snnf  Njs  snf 7f)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.
rr   r?   rs   ru   Nrv   )asynciogatherrx   r*   rg   r   ry   rz   rA   r{   r   r}   r~   s           r%   rf   EnsembleRetriever.arank_fusion   s     &  '~~ %.doo$>	 %?LA !! "-"7"7jQ<P"7"Q %?	 
 
 s>*+A *,!,C 3=S(2K2Kc*QTT,!N , ,,^<<)	
!s.   )C8C
#C+C,!C)C6!CC	doc_listsc                   ^ ^ [        U5      [        T R                  5      :w  a  Sn[        U5      e[        [        5      m[        UT R                  5       Hd  u  p4[        USS9 HQ  u  pVTT R                  c  UR                  OUR                  T R                     ==   XET R                  -   -  -  ss'   MS     Mf     [        R                  " U5      n[        [        UU 4S j5      SUU 4S jS9$ )ay  
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?   )startc                 h   > TR                   c  U R                  $ U R                  TR                      $ r1   r.   rw   rN   )r   r8   s    r%   <lambda><EnsembleRetriever.weighted_reciprocal_rank.<locals>.<lambda>F  s2    {{* $$ 3dkk23r:   Tc                 r   > TTR                   c  U R                     $ U R                  TR                         $ r1   r   )r   	rrf_scorer8   s    r%   r   r   M  s1    I$(KK$7  =@\\$++=Vr:   )reverser   )rA   r+   
ValueErrorr   floatziprx   r.   rw   rN   r-   r   from_iterablesortedr&   )	r8   r   msgdoc_listweightrankr   all_docsr   s	   `       @r%   r}   *EnsembleRetriever.weighted_reciprocal_rank   s      y>S..PCS/! '2%&8	 #It|| <H&xq9	  ;;. (( \\$++6	 dff}-.  : != &&y1 
 	
r:    r1   )#__name__
__module____qualname____firstlineno____doc__listr   __annotations__r   r-   intr.   r
   r|   propertyr   r2   r   classmethoddictr   rD   r   r   r   rb   rg   r   rl   r   ro   r\   rf   r}   __static_attributes__r   r:   r%   r(   r(   6   s    ]##%[AsK FHSM 
d#89 
 
 (#c3h C   $  ,0"" (" 	"
 
h" "H  ,0&& (& 	&
 
h& &P44 4	4
 
h4&;; 9	;
 
h;0 ,0&=&= 4&=
 (&= 
h&=Z ,0(=(= 9(=
 ((= 
h(=T0
X'0
 
h0
r:   r(   )(r   r   collectionsr   collections.abcr   r   r   	itertoolsr   typingr   r	   r
   r   r   rX   r   r   langchain_core.documentsr   langchain_core.retrieversr   r   langchain_core.runnablesr   langchain_core.runnables.configr   r   langchain_core.runnables.utilsr   r   pydanticr   typing_extensionsr   r   r   r&   r(   r   r:   r%   <module>r      s   
  # 8 8   . B 3 G % &CLCx HQK hsAv.> 8A; "Z
 Z
r:   