
    KKi                         S r SSKJr  SSKJr  SSKJrJrJr  SSK	J
r
Jr  SSKJr  SSKJr  SSKJr  SS	KJr  \" S
SSS9 " S S\5      5       rg)z6Chain that carries on a conversation and calls an LLM.    )
deprecated)BasePromptTemplate)
ConfigDictFieldmodel_validator)Selfoverride)
BaseMemory)PROMPT)LLMChain)ConversationBufferMemoryz0.2.7z;langchain_core.runnables.history.RunnableWithMessageHistoryz1.0)sincealternativeremovalc                       \ rS rSr% Sr\" \S9r\\	S'    \
r\\	S'    Sr\\	S'   Sr\\	S	'   \" S
SS9r\\S\4S j5       5       r\S\\   4S j5       r\" SS9S\4S j5       rSrg)ConversationChain   a
  Chain to have a conversation and load context from memory.

This class is deprecated in favor of `RunnableWithMessageHistory`. Please refer
to this tutorial for more detail: https://python.langchain.com/docs/tutorials/chatbot/

`RunnableWithMessageHistory` offers several benefits, including:

- Stream, batch, and async support;
- More flexible memory handling, including the ability to manage memory
    outside the chain;
- Support for multiple threads.

Below is a minimal implementation, analogous to using `ConversationChain` with
the default `ConversationBufferMemory`:

    ```python
    from langchain_core.chat_history import InMemoryChatMessageHistory
    from langchain_core.runnables.history import RunnableWithMessageHistory
    from langchain_openai import ChatOpenAI


    store = {}  # memory is maintained outside the chain


    def get_session_history(session_id: str) -> InMemoryChatMessageHistory:
        if session_id not in store:
            store[session_id] = InMemoryChatMessageHistory()
        return store[session_id]


    model = ChatOpenAI(model="gpt-3.5-turbo-0125")

    chain = RunnableWithMessageHistory(model, get_session_history)
    chain.invoke(
        "Hi I'm Bob.",
        config={"configurable": {"session_id": "1"}},
    )  # session_id determines thread
    ```

Memory objects can also be incorporated into the `get_session_history` callable:

    ```python
    from langchain_classic.memory import ConversationBufferWindowMemory
    from langchain_core.chat_history import InMemoryChatMessageHistory
    from langchain_core.runnables.history import RunnableWithMessageHistory
    from langchain_openai import ChatOpenAI


    store = {}  # memory is maintained outside the chain


    def get_session_history(session_id: str) -> InMemoryChatMessageHistory:
        if session_id not in store:
            store[session_id] = InMemoryChatMessageHistory()
            return store[session_id]

        memory = ConversationBufferWindowMemory(
            chat_memory=store[session_id],
            k=3,
            return_messages=True,
        )
        assert len(memory.memory_variables) == 1
        key = memory.memory_variables[0]
        messages = memory.load_memory_variables({})[key]
        store[session_id] = InMemoryChatMessageHistory(messages=messages)
        return store[session_id]


    model = ChatOpenAI(model="gpt-3.5-turbo-0125")

    chain = RunnableWithMessageHistory(model, get_session_history)
    chain.invoke(
        "Hi I'm Bob.",
        config={"configurable": {"session_id": "1"}},
    )  # session_id determines thread
    ```

Example:
    ```python
    from langchain_classic.chains import ConversationChain
    from langchain_openai import OpenAI

    conversation = ConversationChain(llm=OpenAI())
    ```
)default_factorymemorypromptinput	input_keyresponse
output_keyTforbid)arbitrary_types_allowedextrareturnc                     g)NF )clss    l/var/www/html/dynamic-report/venv/lib/python3.13/site-packages/langchain_classic/chains/conversation/base.pyis_lc_serializable$ConversationChain.is_lc_serializablew   s         c                     U R                   /$ )z5Use this since so some prompt vars come from history.)r   )selfs    r"   
input_keysConversationChain.input_keys|   s     r%   after)modec                    U R                   R                  nU R                  nX!;   a  SU SU S3n[        U5      eU R                  R
                  n/ UQUPn[        U5      [        U5      :w  a  SU SU SU S3n[        U5      eU $ )z4Validate that prompt input variables are consistent.zThe input key z$ was also found in the memory keys (z+) - please provide keys that don't overlap.z:Got unexpected prompt input variables. The prompt expects z
, but got z as inputs from memory, and z as the normal input key.)r   memory_variablesr   
ValueErrorr   input_variablesset)r'   memory_keysr   msgprompt_variablesexpected_keyss         r"   validate_prompt_input_variables1ConversationChain.validate_prompt_input_variables   s     kk22NN	#  ,= KM  S/!;;661+1y1}%5!66L#$J{m <(k)BD 
 S/!r%   r    N)__name__
__module____qualname____firstlineno____doc__r   r   r   r
   __annotations__r   r   r   r   strr   r   model_configclassmethodr	   boolr#   propertylistr(   r   r   r5   __static_attributes__r    r%   r"   r   r      s    Tl /GHFJH!'F'-Is J  $L
 4     DI     '"  #r%   r   N)r;   langchain_core._apir   langchain_core.promptsr   pydanticr   r   r   typing_extensionsr   r	   langchain_classic.base_memoryr
   ,langchain_classic.chains.conversation.promptr   langchain_classic.chains.llmr   langchain_classic.memory.bufferr   r   r    r%   r"   <module>rL      sO    < * 5 7 7 , 4 ? 1 D 
M
B B
Br%   