
    Ng#-                     n   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dededee         dee         de$de$deee$ef         ef         fdZ% eddd           G 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                   t          |           |pt          |pt                      }dt          dt          ffd}t          j        di |i                    d          |z  | z  |z                      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                 R                         fd|          D                       S )Nc              3   8   K   | ]}t          |          V  d S N)r   ).0doc_document_prompts     d/var/www/html/ai-engine/env/lib/python3.11/site-packages/langchain/chains/combine_documents/stuff.py	<genexpr>zDcreate_stuff_documents_chain.<locals>.format_docs.<locals>.<genexpr>T   sB       '
 '
 C!122'
 '
 '
 '
 '
 '
    )join)r#   r)   r   r   s    r*   format_docsz1create_stuff_documents_chain.<locals>.format_docsS   sG    !&& '
 '
 '
 '
45'
 '
 '
 
 
 	
r,   format_inputs)run_namestuff_documents_chain )r   r   r   dictstrr   assignwith_config)	r   r    r   r   r   r   _output_parserr.   r)   s	       ``  @r*   create_stuff_documents_chainr8      s    n V3444&A*A"7o&7&7N
D 
S 
 
 
 
 
 
 
 
 	"KK&<k%JKKWW$ 	X 	
 	
 	 		
 	 k2k334r,   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/)sinceremovalmessagec                       e Zd ZU dZeed<   	  ed           Zeed<   	 e	ed<   	 dZ
e	ed<   	  ed	d
          Z ed          ededefd                        Zedee	         f fd            Zdee         dedefdZdee         dedee         fdZ	 ddee         dededee	ef         fdZ	 ddee         dededee	ef         fdZede	fd            Z x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                      t           S r&   )r   r2   r,   r*   <lambda>zStuffDocumentsChain.<lambda>   s     7 r,   )default_factoryr   r   z

r   Tforbid)arbitrary_types_allowedextrabefore)modevaluesr!   c                     |d         j         j        }d|vr.t          |          dk    r|d         |d<   n4t          d          |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.
        r>   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)clsrG   llm_chain_variabless      r*   "get_default_document_variable_namez6StuffDocumentsChain.get_default_document_variable_name   s     %[18H#611&''1,,3Fq3I/00 3  
 ./7JJJ Uf5M.N U U?RU U   r,   c                 b      fd j         j        D             }t                      j        |z   S )Nc                 *    g | ]}|j         k    |S r2   )r   )r'   kselfs     r*   
<listcomp>z2StuffDocumentsChain.input_keys.<locals>.<listcomp>   s-     
 
 
A9T4T4TA4T4T4Tr,   )r>   
input_keyssuper)rS   
extra_keys	__class__s   ` r*   rU   zStuffDocumentsChain.input_keys   sE    
 
 
 
~0
 
 

 ww!J..r,   docskwargsc                       fd|D             } f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                 :    g | ]}t          |j                  S r2   )r   r   )r'   r(   rS   s     r*   rT   z3StuffDocumentsChain._get_inputs.<locals>.<listcomp>   s&    RRRcsD,@AARRRr,   c                 B    i | ]\  }}|j         j        j        v ||S r2   )r>   r    rJ   )r'   rR   vrS   s      r*   
<dictcomp>z3StuffDocumentsChain._get_inputs.<locals>.<dictcomp>   s<     
 
 
1DN)999 q999r,   )itemsr   r-   r   )rS   rY   rZ   doc_stringsr#   s   `    r*   _get_inputszStuffDocumentsChain._get_inputs   st      SRRRTRRR
 
 
 

 
 

 /3.E.J.J;.W.Wt*+r,   c                      | j         |fi |} | j        j        j        d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.
        r2   )rb   r>   r    format_get_num_tokens)rS   rY   rZ   r#   r    s        r*   prompt_lengthz!StuffDocumentsChain.prompt_length   sQ      "!$11&11-&-7777~--f555r,   N	callbacksc                 J     | j         |fi |} | j        j        d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.
        rg   r2   )rb   r>   predictrS   rY   rg   rZ   r#   s        r*   combine_docsz StuffDocumentsChain.combine_docs   sC     "!$11&11%t~%DD	DVDDbHHr,   c                 Z   K    | j         |fi |} | j        j        dd|i| d{V 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.
        rg   Nr2   )rb   r>   apredictrj   s        r*   acombine_docsz!StuffDocumentsChain.acombine_docs  sY       "!$11&11,T^,KKyKFKKKKKKKKROOr,   c                     dS )Nr1   r2   )rS   s    r*   _chain_typezStuffDocumentsChain._chain_type  s    &&r,   r&   )!__name__
__module____qualname____doc__r   __annotations__r   r   r   r4   r   r   model_configr   classmethodr   r   rO   propertyr   rU   r
   r3   rb   r   intrf   r	   r   rk   rn   rp   __classcell__)rX   s   @r*   r=   r=   c   s_        # #J $*/%77+ + +O'    SI$$$$?: $  L
 _(###     [ $#0 /DI / / / / / X/X # $    46$x. 6C 6HSM 6 6 6 6* <@I INI/8IKNI	sDy	I I I I& <@P PNP/8PKNP	sDy	P P P P$ 'S ' ' ' X' ' ' ' 'r,   r=   )'rt   typingr   r   r   r   r   langchain_core._apir   langchain_core.callbacksr	   langchain_core.documentsr
   langchain_core.language_modelsr   langchain_core.output_parsersr   r   langchain_core.promptsr   r   langchain_core.runnablesr   r   pydanticr   r   r   'langchain.chains.combine_documents.baser   r   r   r   r   langchain.chains.llmr   r4   r8   r=   r2   r,   r*   <module>r      sB   = = 3 3 3 3 3 3 3 3 3 3 3 3 3 3 * * * * * * . . . . . . - - - - - - < < < < < < K K K K K K K K F F F F F F F F B B B B B B B B 7 7 7 7 7 7 7 7 7 7              * ) ) ) ) ) 15488"/H4 H4 H4	H4H4 ,-	H4
 01H4 H4  H4 d38nc!"H4 H4 H4 H4V 
	X	  m' m' m' m' m'3 m' m' m' m' m'r,   