a
    ag#-                     @   s  d Z ddlmZmZ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 ddlmZmZ ddlmZmZ dd	lmZmZ dd
lmZmZmZ ddlmZmZmZm Z m!Z! ddl"m#Z# ddeedeeee ee e$e$eee$ef ef dddZ%eddddG dd de Z&dS )z7Chain that combines documents by stuffing into context.    )AnyDictListOptionalTuple)
deprecated)	Callbacks)Document)LanguageModelLike)BaseOutputParserStrOutputParser)BasePromptTemplateformat_document)RunnableRunnablePassthrough)
ConfigDictFieldmodel_validator)DEFAULT_DOCUMENT_PROMPTDEFAULT_DOCUMENT_SEPARATORDOCUMENTS_KEYBaseCombineDocumentsChain_validate_prompt)LLMChainN)output_parserdocument_promptdocument_separatordocument_variable_name)llmpromptr   r   r   r   returnc                   sd   t | |pt |pt }ttd fdd}tjf i |ijdd|B | B |B jddS )a  Create a chain for passing a list of Documents to a model.

    Args:
        llm: Language model.
        prompt: Prompt template. Must contain input variable "context" (override by
            setting document_variable), which will be used for passing in the formatted documents.
        output_parser: Output parser. Defaults to StrOutputParser.
        document_prompt: Prompt used for formatting each document into a string. Input
            variables can be "page_content" or any metadata keys that are in all
            documents. "page_content" will automatically retrieve the
            `Document.page_content`, and all other inputs variables will be
            automatically retrieved from the `Document.metadata` dictionary. Default to
            a prompt that only contains `Document.page_content`.
        document_separator: String separator to use between formatted document strings.
        document_variable_name: Variable name to use for the formatted documents in the prompt.
            Defaults to "context".

    Returns:
        An LCEL Runnable. The input is a dictionary that must have a "context" key that
        maps to a List[Document], and any other input variables expected in the prompt.
        The Runnable return type depends on output_parser used.

    Example:
        .. code-block:: python

            # pip install -U langchain langchain-community

            from langchain_community.chat_models import ChatOpenAI
            from langchain_core.documents import Document
            from langchain_core.prompts import ChatPromptTemplate
            from langchain.chains.combine_documents import create_stuff_documents_chain

            prompt = ChatPromptTemplate.from_messages(
                [("system", "What are everyone's favorite colors:\n\n{context}")]
            )
            llm = ChatOpenAI(model="gpt-3.5-turbo")
            chain = create_stuff_documents_chain(llm, prompt)

            docs = [
                Document(page_content="Jesse loves red but not yellow"),
                Document(page_content = "Jamal loves green but not as much as he loves orange")
            ]

            chain.invoke({"context": docs})
    )inputsr    c                    s     fdd|  D S )Nc                 3   s   | ]}t | V  qd S N)r   .0doc)_document_prompt v/var/www/html/cobodadashboardai.evdpl.com/venv/lib/python3.9/site-packages/langchain/chains/combine_documents/stuff.py	<genexpr>T   s   zDcreate_stuff_documents_chain.<locals>.format_docs.<locals>.<genexpr>)join)r!   r&   r   r   r'   r(   format_docsS   s    z1create_stuff_documents_chain.<locals>.format_docsZformat_inputs)Zrun_namestuff_documents_chain)r   r   r   dictstrr   ZassignZwith_config)r   r   r   r   r   r   Z_output_parserr,   r'   r+   r(   create_stuff_documents_chain   s     7

r0   z0.2.13z1.0zThis class is deprecated. Use the `create_stuff_documents_chain` constructor instead. See migration guide here: https://python.langchain.com/docs/versions/migrating_chains/stuff_docs_chain/)ZsinceZremovalmessagec                       s  e Zd ZU dZeed< edd dZeed< e	ed< dZ
e	ed	< ed
ddZeddeeedddZeee	 d fddZee eedddZee eee dddZd"ee eeee	ef dddZd#ee eeee	ef dddZee	dd d!Z  Z S )$StuffDocumentsChaina-  Chain that combines documents by stuffing into context.

    This chain takes a list of documents and first combines them into a single string.
    It does this by formatting each document into a string with the `document_prompt`
    and then joining them together with `document_separator`. It then adds that new
    string to the inputs with the variable name set by `document_variable_name`.
    Those inputs are then passed to the `llm_chain`.

    Example:
        .. code-block:: python

            from langchain.chains import StuffDocumentsChain, LLMChain
            from langchain_core.prompts import PromptTemplate
            from langchain_community.llms import OpenAI

            # This controls how each document will be formatted. Specifically,
            # it will be passed to `format_document` - see that function for more
            # details.
            document_prompt = PromptTemplate(
                input_variables=["page_content"],
                template="{page_content}"
            )
            document_variable_name = "context"
            llm = OpenAI()
            # The prompt here should take as an input variable the
            # `document_variable_name`
            prompt = PromptTemplate.from_template(
                "Summarize this content: {context}"
            )
            llm_chain = LLMChain(llm=llm, prompt=prompt)
            chain = StuffDocumentsChain(
                llm_chain=llm_chain,
                document_prompt=document_prompt,
                document_variable_name=document_variable_name
            )
    	llm_chainc                   C   s   t S r"   )r   r'   r'   r'   r(   <lambda>       zStuffDocumentsChain.<lambda>)default_factoryr   r   z

r   TZforbid)Zarbitrary_types_allowedextrabefore)mode)valuesr    c                 C   s`   |d j j}d|vr8t|dkr.|d |d< q\tdn$|d |vr\td|d  d| |S )zGet default document variable name, if not provided.

        If only one variable is present in the llm_chain.prompt,
        we can infer that the formatted documents should be passed in
        with this variable name.
        r3   r      r   zQdocument_variable_name must be provided if there are multiple llm_chain_variableszdocument_variable_name z- was not found in llm_chain input_variables: )r   input_variableslen
ValueError)clsr:   Zllm_chain_variablesr'   r'   r(   "get_default_document_variable_name   s    	z6StuffDocumentsChain.get_default_document_variable_name)r    c                    s"    fdd j jD }t j| S )Nc                    s   g | ]}| j kr|qS r'   )r   )r$   kselfr'   r(   
<listcomp>   s   z2StuffDocumentsChain.input_keys.<locals>.<listcomp>)r3   
input_keyssuper)rC   Z
extra_keys	__class__rB   r(   rE      s    
zStuffDocumentsChain.input_keys)docskwargsr    c                    s>    fdd|D } fdd|  D } j|| j< |S )a  Construct inputs from kwargs and docs.

        Format and then join all the documents together into one input with name
        `self.document_variable_name`. Also pluck any additional variables
        from **kwargs.

        Args:
            docs: List of documents to format and then join into single input
            **kwargs: additional inputs to chain, will pluck any other required
                arguments from here.

        Returns:
            dictionary of inputs to LLMChain
        c                    s   g | ]}t | jqS r'   )r   r   r#   rB   r'   r(   rD      r5   z3StuffDocumentsChain._get_inputs.<locals>.<listcomp>c                    s$   i | ]\}}| j jjv r||qS r'   )r3   r   r<   )r$   rA   vrB   r'   r(   
<dictcomp>   s   z3StuffDocumentsChain._get_inputs.<locals>.<dictcomp>)itemsr   r*   r   )rC   rI   rJ   Zdoc_stringsr!   r'   rB   r(   _get_inputs   s    
zStuffDocumentsChain._get_inputsc                 K   s2   | j |fi |}| jjjf i |}| j|S )aV  Return the prompt length given the documents passed in.

        This can be used by a caller to determine whether passing in a list
        of documents would exceed a certain prompt length. This useful when
        trying to ensure that the size of a prompt remains below a certain
        context limit.

        Args:
            docs: List[Document], a list of documents to use to calculate the
                total prompt length.

        Returns:
            Returns None if the method does not depend on the prompt length,
            otherwise the length of the prompt in tokens.
        )rN   r3   r   formatZ_get_num_tokens)rC   rI   rJ   r!   r   r'   r'   r(   prompt_length   s    z!StuffDocumentsChain.prompt_lengthN)rI   	callbacksrJ   r    c                 K   s,   | j |fi |}| jjf d|i|i fS )a  Stuff all documents into one prompt and pass to LLM.

        Args:
            docs: List of documents to join together into one variable
            callbacks: Optional callbacks to pass along
            **kwargs: additional parameters to use to get inputs to LLMChain.

        Returns:
            The first element returned is the single string output. The second
            element returned is a dictionary of other keys to return.
        rQ   )rN   r3   ZpredictrC   rI   rQ   rJ   r!   r'   r'   r(   combine_docs   s    z StuffDocumentsChain.combine_docsc                    s2   | j |fi |}| jjf d|i|I dH i fS )a  Async stuff all documents into one prompt and pass to LLM.

        Args:
            docs: List of documents to join together into one variable
            callbacks: Optional callbacks to pass along
            **kwargs: additional parameters to use to get inputs to LLMChain.

        Returns:
            The first element returned is the single string output. The second
            element returned is a dictionary of other keys to return.
        rQ   N)rN   r3   ZapredictrR   r'   r'   r(   acombine_docs  s    z!StuffDocumentsChain.acombine_docsc                 C   s   dS )Nr-   r'   rB   r'   r'   r(   _chain_type  s    zStuffDocumentsChain._chain_type)N)N)!__name__
__module____qualname____doc__r   __annotations__r   r   r   r/   r   r   Zmodel_configr   classmethodr   r   r@   propertyr   rE   r	   r.   rN   r   intrP   r   r   rS   rT   rU   __classcell__r'   r'   rG   r(   r2   c   s<   

% 

 

r2   )'rY   typingr   r   r   r   r   Zlangchain_core._apir   Zlangchain_core.callbacksr   Zlangchain_core.documentsr	   Zlangchain_core.language_modelsr
   Zlangchain_core.output_parsersr   r   Zlangchain_core.promptsr   r   Zlangchain_core.runnablesr   r   Zpydanticr   r   r   Z'langchain.chains.combine_documents.baser   r   r   r   r   Zlangchain.chains.llmr   r/   r0   r2   r'   r'   r'   r(   <module>   s<   K	