
    ih&                     &   d dl Z d dlZd dlmZmZmZ d dlmZmZ d dl	m
Z
 d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ  ej2                  e      Z G d deee            Z edgd      Zdee
   dee
   fdZ G d de      Z y)    N)ListOptionalSequence)#AsyncCallbackManagerForRetrieverRunCallbackManagerForRetrieverRun)Document)BaseLanguageModel)BaseOutputParser)BasePromptTemplate)PromptTemplate)BaseRetriever)Runnable)LLMChainc                   &    e Zd ZdZdedee   fdZy)LineListOutputParserz"Output parser for a list of lines.textreturnc                 j    |j                         j                  d      }t        t        d |            S )N
)stripsplitlistfilter)selfr   liness      ^/var/www/html/dev/engine/venv/lib/python3.12/site-packages/langchain/retrievers/multi_query.pyparsezLineListOutputParser.parse   s*    

""4(F4'((    N)__name__
__module____qualname____doc__strr   r    r   r   r   r      s    ,)# )$s) )r   r   questiona  You are an AI language model assistant. Your task is 
    to generate 3 different versions of the given user 
    question to retrieve relevant documents from a vector  database. 
    By generating multiple perspectives on the user question, 
    your goal is to help the user overcome some of the limitations 
    of distance-based similarity search. Provide these alternative 
    questions separated by newlines. Original question: {question})input_variablestemplate	documentsr   c                 Z    t        |       D cg c]  \  }}|| d | vs| c}}S c c}}w )N)	enumerate)r(   idocs      r   _unique_documentsr-   +   s,    '	2OFAsc2A6NCOOOs   ''c                   P   e Zd ZU dZeed<   eed<   dZeed<   dZ	e
ed<   	 dZeed	<   	 eed
dfdedededee
   d	edd fd       Zde
dedee   fdZde
dedee
   fdZ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ee
   dedee   fdZdee   dee   fdZy
)MultiQueryRetrieverzGiven a query, use an LLM to write a set of queries.

    Retrieve docs for each query. Return the unique union of all retrieved docs.
    	retriever	llm_chainTverboser   
parser_keyFinclude_originalNllmpromptr   c                 <    t               }||z  |z  } | |||      S )a  Initialize from llm using default template.

        Args:
            retriever: retriever to query documents from
            llm: llm for query generation using DEFAULT_QUERY_PROMPT
            prompt: The prompt which aims to generate several different versions
                of the given user query
            include_original: Whether to include the original query in the list of
                generated queries.

        Returns:
            MultiQueryRetriever
        )r0   r1   r4   )r   )clsr0   r5   r6   r3   r4   output_parserr1   s           r   from_llmzMultiQueryRetriever.from_llm=   s0    , -.SL=0	-
 	
r   queryrun_managerc                   K   | j                  ||       d{   }| j                  r|j                  |       | j                  ||       d{   }| j	                  |      S 7 L7 w)Get relevant documents given a user query.

        Args:
            query: user query

        Returns:
            Unique union of relevant documents from all generated queries
        N)agenerate_queriesr4   appendaretrieve_documentsunique_unionr   r;   r<   queriesr(   s        r   _aget_relevant_documentsz,MultiQueryRetriever._aget_relevant_documents[   se      ..ukBB  NN5!227KHH	  ++	 C Is!   A)A%6A)A'A)'A)r%   c                   K   | j                   j                  d|id|j                         i       d{   }t        | j                   t              r|d   }n|}| j
                  rt        j                  d|        |S 7 Lw)Generate queries based upon user input.

        Args:
            question: user query

        Returns:
            List of LLM generated queries that are similar to the user input
        r%   	callbacksconfigNr   Generated queries: )r1   ainvoke	get_child
isinstancer   r2   loggerinfor   r%   r<   responser   s        r   r?   z%MultiQueryRetriever.agenerate_querieso   s      //"K9N9N9P+Q 0 
 
 dnnh/V$EE<<KK-eW56
s   3BBABrD   c                     K   t        j                   fd|D          d{   }|D cg c]  }|D ]  }|  c}}S 7 c c}}w w)Run all LLM generated queries.

        Args:
            queries: query list

        Returns:
            List of retrieved Documents
        c              3   x   K   | ]1  }j                   j                  |d j                         i       3 yw)rH   rI   N)r0   rL   rM   ).0r;   r<   r   s     r   	<genexpr>z:MultiQueryRetriever.aretrieve_documents.<locals>.<genexpr>   sB        &&;0E0E0G"H ' s   7:N)asynciogather)r   rD   r<   document_listsdocsr,   s   ` `   r   rA   z'MultiQueryRetriever.aretrieve_documents   sU       '~~ %	 
 
 !/?$?3???
 @s    A
A	A
AA
A
c                    | j                  ||      }| j                  r|j                  |       | j                  ||      }| j	                  |      S )r>   )generate_queriesr4   r@   retrieve_documentsrB   rC   s        r   _get_relevant_documentsz+MultiQueryRetriever._get_relevant_documents   sN     ''{;  NN5!++G[A	  ++r   c                     | j                   j                  d|id|j                         i      }t        | j                   t              r|d   }n|}| j
                  rt        j                  d|        |S )rG   r%   rH   rI   r   rK   )r1   invokerM   rN   r   r2   rO   rP   rQ   s        r   r]   z$MultiQueryRetriever.generate_queries   st     >>(("K9N9N9P+Q ) 
 dnnh/V$EE<<KK-eW56r   c                     g }|D ]@  }| j                   j                  |d|j                         i      }|j                  |       B |S )rT   rH   rI   )r0   ra   rM   extend)r   rD   r<   r(   r;   r[   s         r   r^   z&MultiQueryRetriever.retrieve_documents   s\     	 	#E>>(({K,A,A,CD ) D T"		#
 r   r(   c                     t        |      S )zGet unique Documents.

        Args:
            documents: List of retrieved Documents

        Returns:
            List of unique retrieved Documents
        )r-   )r   r(   s     r   rB   z MultiQueryRetriever.unique_union   s     !++r   )r   r    r!   r"   r   __annotations__r   r2   boolr3   r#   r4   classmethodDEFAULT_QUERY_PROMPTr	   r   r   r:   r   r   r   rE   r?   rA   r   r_   r]   r^   rB   r$   r   r   r/   r/   /   s   
 GTJO"d"Q
 &:$(!&
 
 
 #	

 SM
 
 

 
:,, 9	,
 
h,(*M	c,@Cy@/R@	h@*,, 4	,
 
h,(*H	c,Cy/M	h&	,d8n 	,h 	,r   r/   )!rX   loggingtypingr   r   r   langchain_core.callbacksr   r   langchain_core.documentsr   langchain_core.language_modelsr	   langchain_core.output_parsersr
   langchain_core.promptsr   langchain_core.prompts.promptr   langchain_core.retrieversr   langchain_core.runnablesr   langchain.chains.llmr   	getLoggerr   rO   r#   r   rh   r-   r/   r$   r   r   <module>ru      s      + + . < : 5 8 3 - )			8	$)+DI6 ) &LF	 P(!3 PX Pq,- q,r   