Location>code7788 >text

LangChain Basics (03)

Popularity:499 ℃/2025-02-06 16:44:59

LangChain Core Module Learning: Memory

Most LLM applications have a conversation interface. An important part of a conversation is the ability to cite information that was previously described in the conversation. At the very least, a conversation system should be able to directly access windows of some past messages. More complex systems will need to have a constantly updated world model that enables it to maintain information about entities and their relationships.

We call the ability to store past interactive information "memory".

LangChain provides many practical tools for adding Memory to applications/systems. These tools can be used alone or seamlessly integrated into the chain.

A memory system needs to support two basic operations:Read (READ) and Write (WRITE)

Each chain defines some core execution logic and expects certain inputs. Some of these inputs come directly from the user, but some may come from Memory.

In a single run of a typical Chain, it will interact with its Memory System at least twice:

1. After receiving the initial user input, the chain will read and augment the user input from its Memory before executing the core logic.
2. After executing the core logic but before returning the answer, a chain will write the input and output of the currently running to the Memory so that they can be referenced in future runs.

BaseMemory Class

Class inheritance relationship:

## Suitable for simple language models
 BaseMemory --> BaseChatMemory --> <name>Memory # Examples: ZepMemory, MotorheadMemory
# Define a base class called BaseMemory
 class BaseMemory(Serializable, ABC):
     """Abstract base class for memory in Chains.
    
     The memory here refers to the state in Chains.  Memory can be used to store information about Chain's past execution,
     And inject this information into the input of future execution of Chain.  For example, for session-type Chains, memory can be used to
     Store sessions and automatically add them to future model prompts so that the model has the necessary context to coherently
     Respond to the latest input.  """

     # Define a subclass called Config
     class Config:
         """Configure this pydantic object.
    
         Pydantic is a Python library for data verification and setup management, mainly based on Python type prompts.
         """
    
         # Allows any type to be used in pydantic models.  This is often used to allow complex data types.
         arbitrary_types_allowed = True
    
     # Here are some methods that must be implemented by subclasses:
    
     # Define a property, which is an abstract method.  Any subclass derived from BaseMemory needs to implement this method.
     # This method should return the string key that the memory class will be added to the chain input.
     @property
     @abstractmethod
     def memory_variables(self) -> List[str]:
         """Get the string key that this memory class will be added to the chain input."""
    
     # Define an abstract method.  Any subclass derived from BaseMemory needs to implement this method.
     # This method returns key-value pairs based on the given chain input.
     @abstractmethod
     def load_memory_variables(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
         """Return key-value pairs based on text input to the chain."""
    
     # Define an abstract method.  Any subclass derived from BaseMemory needs to implement this method.
     # This method saves the context in which this chain runs to memory.
     @abstractmethod
     def save_context(self, inputs: Dict[str, Any], outputs: Dict[str, str]) -> None:
         """Save the context of this chain running to memory.""""
    
     # Define an abstract method.  Any subclass derived from BaseMemory needs to implement this method.
     # This method clears the memory contents.
     @abstractmethod
     def clear(self) -> None:
         """Clear memory content."""

BaseChatMessageHistory Class

Class inheritance relationship:

## For chat model

 BaseChatMessageHistory --> <name>ChatMessageHistory # Example: ZepChatMessageHistory
# Define a base class called BaseChatMessageHistory
 class BaseChatMessageHistory(ABC):
     """Abstract base class for chat message history."""

     # List of messages stored in memory
     messages: List[BaseMessage]

     # Define an add_user_message method, which is a convenient method for adding human message strings to the storage area.
     def add_user_message(self, message: str) -> None:
         """A convenient way to add a human message string to store.

         parameter:
             message: String content of human message.
         """
         self.add_message(HumanMessage(content=message))

     # Define an add_ai_message method, which is a convenient method for adding AI message strings to the storage area.
     def add_ai_message(self, message: str) -> None:
         """A convenient way to add an AI message string to storage.

         parameter:
             message: The string content of the AI ​​message.
         """
         self.add_message(AIMessage(content=message))

     # Abstract method needs to be implemented by subclasses that inherit this base class.
     @abstractmethod
     def add_message(self, message: BaseMessage) -> None:
         """Add Message object to the store.

         parameter:
             message: The BaseMessage object to be stored.
         """
         raise NotImplementedError()

     # Abstract method needs to be implemented by subclasses that inherit this base class.
     @abstractmethod
     def clear(self) -> None:
         """Delete all messages from storage"""

ConversationChain and ConversationBufferMemory

ConversationBufferMemoryCan be used to store messages and extract messages into a variable.

from langchain_openai import OpenAI
from  import ConversationChain
from  import ConversationBufferMemory

llm = OpenAI(temperature=0)
conversation = ConversationChain(
    llm=llm, 
    verbose=True, 
    memory=ConversationBufferMemory()
)
> Entering new ConversationChain chain...
 Prompt after formatting:
 The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.
 Current conversation:
 Human: hello!
 AI:
 [INFO][2025-02-06 16:35:18.141] :304 [t:3812]: successfully refresh token
 > Finished chain.

ConversationBufferWindowMemory

ConversationBufferWindowMemoryA list of interactions for conversations is kept on the timeline. It uses only the last K interactions. This is very useful for maintaining sliding windows for the most recent interactions to avoid oversized buffers.

from import ConversationBufferWindowMemory

 conversation_with_summary = ConversationChain(
     llm=OpenAI(temperature=0, max_tokens=1000),
     # We set a low k=2, to only keep the last 2 interactions in memory
     memory=ConversationBufferWindowMemory(k=2),
     verbose=True
 )
 conversation_with_summary.predict(input="Hi, how are you doing recently?")

ConversationSummaryBufferMemory

ConversationSummaryBufferMemoryThe most recent interaction buffers are preserved in memory, but not just to completely clear old interactions, but to compile them into digests and use them simultaneously. Unlike previous implementations, it uses token length instead of interactions to determine when to clear the interaction.

from import ConversationSummaryBufferMemory

 memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=10)
 memory.save_context({"input": "Hi, how are you doing recently?"}, {"output": " Hi! I've been doing well recently, thank you for asking. I've been learning new knowledge recently,  And trying to improve my performance. I'm also trying to communicate more to better understand the way humans think. "})
 memory.save_context({"input": "What new knowledge have you learned recently?"}, {"output": " Recently I learned about natural language processing and how to better understand human language. I  Also learned about machine learning and how to use it to improve your own performance. "})
memory.load_memory_variables({})