U
    h.                     @  sV  d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	m
Z
mZ ddlmZ ddlmZmZmZ ddlmZ dd	lmZ dd
l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ddddG dd de Z+eddddG dd de+Z,eddddG dd de+Z-dS )7Chain for question-answering against a vector database.    )annotationsN)abstractmethod)AnyDictListOptional)
deprecated)AsyncCallbackManagerForChainRunCallbackManagerForChainRun	Callbacks)Document)BaseLanguageModel)PromptTemplate)Fieldroot_validator)BaseRetriever)VectorStore)Chain)BaseCombineDocumentsChain)StuffDocumentsChain)LLMChainload_qa_chain)PROMPT_SELECTORz0.2.13z1.0zThis class is deprecated. Use the `create_retrieval_chain` constructor instead. See migration guide here: https://python.langchain.com/v0.2/docs/versions/migrating_chains/retrieval_qa/)ZsinceZremovalmessagec                	   @  s   e Zd ZU dZded< dZded< dZded< d	Zd
ed< G dd dZe	ddddZ
e	ddddZed1dddddd dddZed2ddddd ddd Zedd!d"d#d$d%Zd3d&d'd&d(d)d*Zedd+d"d#d,d-Zd4d&d.d&d(d/d0ZdS )5BaseRetrievalQAz)Base class for question-answering chains.r   combine_documents_chainquerystr	input_keyresult
output_keyFboolreturn_source_documentsc                   @  s   e Zd ZdZdZdZdS )zBaseRetrievalQA.ConfigTZforbidN)__name__
__module____qualname__Zallow_population_by_field_nameZarbitrary_types_allowedextra r)   r)   F/tmp/pip-unpacked-wheel-bo69hh5q/langchain/chains/retrieval_qa/base.pyConfig2   s   r+   z	List[str]returnc                 C  s   | j gS )z,Input keys.

        :meta private:
        )r    selfr)   r)   r*   
input_keys7   s    zBaseRetrievalQA.input_keysc                 C  s   | j g}| jr|dg }|S )z-Output keys.

        :meta private:
        source_documents)r"   r$   )r/   Z_output_keysr)   r)   r*   output_keys?   s    
zBaseRetrievalQA.output_keysNr   zOptional[PromptTemplate]r   zOptional[dict]r   )llmprompt	callbacksllm_chain_kwargskwargsr-   c           
      K  sZ   |pt |}tf |||d|p"i }tdgdd}t|d||d}	| f |	|d|S )zInitialize from LLM.)r3   r4   r5   Zpage_contentzContext:
{page_content})Zinput_variablestemplatecontext)	llm_chainZdocument_variable_namedocument_promptr5   )r   r5   )r   Z
get_promptr   r   r   )
clsr3   r4   r5   r6   r7   Z_promptr:   r;   r   r)   r)   r*   from_llmJ   s0    
   zBaseRetrievalQA.from_llmstuff)r3   
chain_typechain_type_kwargsr7   r-   c                 K  s.   |pi }t |fd|i|}| f d|i|S )zLoad chain from chain type.r?   r   r   )r<   r3   r?   r@   r7   Z_chain_type_kwargsr   r)   r)   r*   from_chain_typeh   s    	zBaseRetrievalQA.from_chain_typer   List[Document]questionrun_managerr-   c                C  s   dS z,Get documents to do question answering over.Nr)   r/   rD   rE   r)   r)   r*   	_get_docsw   s    zBaseRetrievalQA._get_docsDict[str, Any]z$Optional[CallbackManagerForChainRun])inputsrE   r-   c                 C  s~   |p
t  }|| j }dt| jjk}|r<| j||d}n
| |}| jj|||	 d}| j
rp| j|d|iS | j|iS dS )h  Run get_relevant_text and llm on input query.

        If chain has 'return_source_documents' as 'True', returns
        the retrieved documents as well under the key 'source_documents'.

        Example:
        .. code-block:: python

        res = indexqa({'query': 'This is my query'})
        answer, docs = res['result'], res['source_documents']
        rE   rE   Zinput_documentsrD   r5   r1   N)r   get_noop_managerr    inspect	signaturerH   
parametersr   run	get_childr$   r"   r/   rJ   rE   Z_run_managerrD   Zaccepts_run_managerdocsZanswerr)   r)   r*   _call   s    

  zBaseRetrievalQA._callr
   c                  s   dS rF   r)   rG   r)   r)   r*   
_aget_docs   s    zBaseRetrievalQA._aget_docsz)Optional[AsyncCallbackManagerForChainRun]c                   s   |p
t  }|| j }dt| jjk}|rB| j||dI dH }n| |I dH }| jj|||	 dI dH }| j
r| j|d|iS | j|iS dS )rK   rE   rL   NrM   r1   )r
   rN   r    rO   rP   rW   rQ   r   ZarunrS   r$   r"   rT   r)   r)   r*   _acall   s    
  zBaseRetrievalQA._acall)NNN)r>   N)N)N)r%   r&   r'   __doc____annotations__r    r"   r$   r+   propertyr0   r2   classmethodr=   rA   r   rH   rV   rW   rX   r)   r)   r)   r*   r      s6   


      " r   z0.1.17c                   @  sZ   e Zd ZU dZeddZded< dddd	d
dZdddd	ddZe	ddddZ
dS )RetrievalQAa  Chain for question-answering against an index.

    This class is deprecated. See below for an example implementation using
    `create_retrieval_chain`:

        .. code-block:: python

            from langchain.chains import create_retrieval_chain
            from langchain.chains.combine_documents import create_stuff_documents_chain
            from langchain_core.prompts import ChatPromptTemplate
            from langchain_openai import ChatOpenAI


            retriever = ...  # Your retriever
            llm = ChatOpenAI()

            system_prompt = (
                "Use the given context to answer the question. "
                "If you don't know the answer, say you don't know. "
                "Use three sentence maximum and keep the answer concise. "
                "Context: {context}"
            )
            prompt = ChatPromptTemplate.from_messages(
                [
                    ("system", system_prompt),
                    ("human", "{input}"),
                ]
            )
            question_answer_chain = create_stuff_documents_chain(llm, prompt)
            chain = create_retrieval_chain(retriever, question_answer_chain)

            chain.invoke({"input": query})

    Example:
        .. code-block:: python

            from langchain_community.llms import OpenAI
            from langchain.chains import RetrievalQA
            from langchain_community.vectorstores import FAISS
            from langchain_core.vectorstores import VectorStoreRetriever
            retriever = VectorStoreRetriever(vectorstore=FAISS(...))
            retrievalQA = RetrievalQA.from_llm(llm=OpenAI(), retriever=retriever)

    T)excluder   	retrieverr   r   rB   rC   c                C  s   | j j|d| idS )	Get docs.r5   config)r_   ZinvokerS   rG   r)   r)   r*   rH     s     
zRetrievalQA._get_docsr
   c                  s   | j j|d| idI dH S )r`   r5   ra   N)r_   ZainvokerS   rG   r)   r)   r*   rW     s     
zRetrievalQA._aget_docsr,   c                 C  s   dS )Return the chain type.Zretrieval_qar)   r.   r)   r)   r*   _chain_type  s    zRetrievalQA._chain_typeN)r%   r&   r'   rY   r   r_   rZ   rH   rW   r[   rd   r)   r)   r)   r*   r]      s   

-r]   c                   @  s   e Zd ZU dZedddZded< dZded< d	Zd
ed< ee	dZ
ded< edddddddZedddddddZd
dddddZd
dddddZed
ddd Zd!S )"
VectorDBQAr   Tvectorstore)r^   aliasr      intk
similarityr   search_type)default_factoryrI   search_kwargs)prer   )valuesr-   c                 C  s   t d |S )NzR`VectorDBQA` is deprecated - please use `from langchain.chains import RetrievalQA`)warningswarn)r<   rp   r)   r)   r*   raise_deprecation8  s    zVectorDBQA.raise_deprecationc                 C  s,   d|kr(|d }|dkr(t d| d|S )zValidate search type.rl   )rk   mmrsearch_type of  not allowed.)
ValueError)r<   rp   rl   r)   r)   r*   validate_search_type@  s
    zVectorDBQA.validate_search_typer   rB   rC   c                C  sf   | j dkr(| jj|fd| ji| j}n:| j dkrP| jj|fd| ji| j}ntd| j  d|S )r`   rk   rj   rt   ru   rv   )rl   rf   Zsimilarity_searchrj   rn   Zmax_marginal_relevance_searchrw   )r/   rD   rE   rU   r)   r)   r*   rH   I  s$    

zVectorDBQA._get_docsr
   c                  s   t ddS )r`   z!VectorDBQA does not support asyncN)NotImplementedErrorrG   r)   r)   r*   rW   \  s    zVectorDBQA._aget_docsr,   c                 C  s   dS )rc   Zvector_db_qar)   r.   r)   r)   r*   rd   e  s    zVectorDBQA._chain_typeN)r%   r&   r'   rY   r   rf   rZ   rj   rl   dictrn   r   rs   rx   rH   rW   r[   rd   r)   r)   r)   r*   re   #  s   

	re   ).rY   
__future__r   rO   rq   abcr   typingr   r   r   r   Zlangchain_core._apir	   Zlangchain_core.callbacksr
   r   r   Zlangchain_core.documentsr   Zlangchain_core.language_modelsr   Zlangchain_core.promptsr   Zlangchain_core.pydantic_v1r   r   Zlangchain_core.retrieversr   Zlangchain_core.vectorstoresr   Zlangchain.chains.baser   Z'langchain.chains.combine_documents.baser   Z(langchain.chains.combine_documents.stuffr   Zlangchain.chains.llmr   Z#langchain.chains.question_answeringr   Z0langchain.chains.question_answering.stuff_promptr   r   r]   re   r)   r)   r)   r*   <module>   sL   	 '	L	