In LangChain, memory-enabled applications, such as chatbots, maintain conversation context across multiple turns, whereas applications without memory treat each interaction as independent. This creates a smooth, connected experience where each response builds on previous messages.
In LangChain, memory is used when an application requires access to information from earlier messages, such as in multi-turn conversations or personalized interactions.
A Runnable is a key building block designed to standardize the execution of different components, such as prompts, models, and chains. This makes it easy to invoke different components using the same pattern, reducing complexity when building workflows.
ChatPromptTemplateThe ChatPromptTemplate class creates structured prompts for chat-based interactions. It combines system messages, conversation history, and user input into a single, organized format that the language model can process.
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder# Create chat prompt templateprompt = ChatPromptTemplate.from_messages([("system", "You are a helpful assistant."),MessagesPlaceholder(variable_name="history"),("human", "{input}")])
LangChain uses three primary message types to structure conversations:
SystemMessage: defines the AI assistant’s behavior and roleHumanMessage: represents user inputAIMessage: represents the AI’s responseThis structure creates clear role definitions within conversations.
from langchain_core.messages import SystemMessage, HumanMessage, AIMessagemessages = [SystemMessage(content="You are a helpful assistant."),HumanMessage(content="What's the weather today?"),AIMessage(content="Today's weather is sunny and warm.")]for msg in messages:print(f"{msg.type}: {msg.content}")
MessagesPlaceholderThe MessagesPlaceholder component reserves a spot in your prompt template for conversation history. It allows you to dynamically inject previous messages when the prompt is executed, ensuring the language model has access to past context.
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder# Create prompt with placeholder for conversation historyprompt = ChatPromptTemplate.from_messages([("system", "You are a helpful assistant."),MessagesPlaceholder(variable_name="history"),("human", "{input}")])
InMemoryChatMessageHistoryThe InMemoryChatMessageHistory class allows you to maintain a log of messages exchanged between the user and the model during a conversation. All messages are stored directly in application memory, making it a convenient choice for tracking temporary conversations during a session.
from langchain_core.chat_history import InMemoryChatMessageHistorychat_history = InMemoryChatMessageHistory()chat_history.add_user_message("Hello, how can I help you today?")chat_history.add_ai_message("I'm doing well, thank you!")for message in chat_history.messages:print(f"{message.type}: {message.content}")
session_idA session_id acts as a unique identifier for each conversation, ensuring messages are associated with the correct conversation history. Each session maintains its own separate history, preventing conversations from mixing.
# Use session_id to identify different conversationsresponse = conversation_chain.invoke({"input": "Hello!"},config={"configurable": {"session_id": "session-123"}})
In LangChain, memory is added by passing a memory object during chain creation and including a placeholder in the prompt template for conversation history. This integration allows the model to access past interactions when generating responses.
RunnableWithMessageHistoryThe RunnableWithMessageHistory class in LangChain enhances your existing Runnable by automatically managing the message history. It loads conversation history before processing and saves new messages after processing, maintaining context across conversation turns without manual tracking.
from langchain_core.runnables.history import RunnableWithMessageHistory# Assuming base_chain and get_session_history are definedconversation_chain = RunnableWithMessageHistory(base_chain,get_session_history,input_messages_key="input",history_messages_key="history")
For memory to work correctly in LangChain, the memory component must match the chain’s configuration. This means using consistent variable names and appropriate memory types. Proper alignment prevents runtime errors and ensures smooth data flow through your chain.
The window size parameter controls the number of recent message pairs (exchanges) to keep in memory. Setting k=3 keeps only the last 3 exchanges (6 messages total), discarding older ones. This prevents memory from growing indefinitely.
from langchain_core.chat_history import InMemoryChatMessageHistoryWINDOW_SIZE = 3 # Keep last 3 exchangeswindow_memory = InMemoryChatMessageHistory()# Trim to window sizewindow_memory.messages = window_memory.messages[-(WINDOW_SIZE * 2):]
Hybrid memory achieves a balance between retaining long-term context and managing memory constraints. It stores summaries of older conversations while keeping recent messages in full detail. This approach ensures that the system maintains essential context without overwhelming memory resources.
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholderfrom langchain_core.chat_history import InMemoryChatMessageHistory# Long-term summarized memorysummary = "Project: TaskMaster app. Team: Alex, Jordan, Sam. Sprint 1 done."# Short-term window memoryrecent_memory = InMemoryChatMessageHistory()recent_memory.add_user_message("What’s left for Sprint 2?")recent_memory.add_ai_message("We need to finalize the API and write tests.")# Prompt that uses BOTH summary and recent messagesprompt = ChatPromptTemplate.from_messages([("system", "Project Summary: {summary}"),MessagesPlaceholder(variable_name="recent_messages"),("human", "{input}")])# Inject hybrid memory into the promptmessages = prompt.format_messages(summary=summary,recent_messages=recent_memory.messages,input="What should I work on next?")for msg in messages:print(f"{msg.type}: {msg.content}")
Entity-based memory extracts and stores specific information (like names, locations, or facts) separately from the conversation history. This approach keeps important details accessible without storing complete chat histories, ensuring long-term retention of critical information and improving efficiency.
entity_store = {}entity_store["John Doe"] = {"occupation": "Engineer","location": "New York"}entity_details = entity_store.get("John Doe")print(entity_details)
ConversationSummaryMemory is a memory type in LangChain that uses a language model to create and maintain a running summary of a conversation. It reduces token usage by condensing past exchanges while preserving essential context and key details.
from langchain.memory import ConversationSummaryMemoryfrom langchain.llms import OpenAI# Initialize memory with an LLM summarizerllm = OpenAI(model="gpt-4")summary_memory = ConversationSummaryMemory(llm=llm)# Add conversation entriessummary_memory.add_memory("User: Can you explain LangChain?")summary_memory.add_memory("AI: LangChain is a framework for building LLM-based applications.")summary_memory.add_memory("User: Summarize what we discussed.")# Retrieve the summarized conversationconversation_summary = summary_memory.get_memory()print(conversation_summary)# Output shows a concise summary of key information.
ConversationBufferMemoryConversationBufferMemory is a memory type in LangChain that stores the full conversation history exactly as written. It allows models to access and reference every previous message during an interaction.
from langchain.memory import ConversationBufferMemory# Initialize the memory bufferdialogue_memory = ConversationBufferMemory()# Add conversation entriesdialogue_memory.add_memory("User: What is LangChain?")dialogue_memory.add_memory("AI: LangChain is a framework designed to ...")dialogue_memory.add_memory("User: How does it handle memory?")# Retrieve full conversationdialogue_history = dialogue_memory.get_memory()print(dialogue_history)# Output shows the complete dialogue stored in memory.
LangChain provides convenience methods to add messages to the conversation history.
Use .add_user_message() for user inputs and .add_ai_message() for AI responses. These methods automatically create the correct message types and preserve context.
from langchain_core.chat_history import InMemoryChatMessageHistory# Create conversation historyconversation = InMemoryChatMessageHistory()# Add messages using convenience methodsconversation.add_user_message("Hello, how are you?")conversation.add_ai_message("I'm good, thank you! How can I help you today?")# Inspect conversation historyfor msg in conversation.messages:print(f"{msg.type}: {msg.content}")