mirror of
https://github.com/langchain-ai/memory-template.git
synced 2026-07-01 13:40:54 -04:00
Address comments
This commit is contained in:
@@ -4,29 +4,21 @@
|
||||
[](https://github.com/langchain-ai/memory-template/actions/workflows/integration-tests.yml)
|
||||
[](https://langgraph-studio.vercel.app/templates/open?githubUrl=https://github.com/langchain-ai/memory-template)
|
||||
|
||||
Memory is a powerful way to improve and personalize applications, allowing storage of information (e.g., a user-specific profile or memories) that can be used to inform responses or decisions across multiple interactions. This template provides a simple example of a long-term memory service you can build and deploy using LangGraph.
|
||||
## Motivation
|
||||
|
||||
It has three main components:
|
||||
Memory is a powerful way to improve and personalize AI applications. As an example, memory can be used to store user-specific information across multiple interactions with that user. But, it can also extend to any information that you may want to preserve across multiple interactions with an application. This template show how you can build and deploy a long-term memory service using LangGraph by combining a memory service with a simple chatbot application.
|
||||
|
||||
(1) `Chatbot Graph`: This is a simple chatbot that interacts with a user.
|
||||

|
||||
|
||||
(2) `Memory Graph`: This graph contains the logic for creating memories with customizable schemas from the chatbot's user interactions.
|
||||
## Quickstart
|
||||
|
||||
(3) `Memory Storage`: This stores created memories, making them accessible across multiple user interactions with the chatbot.
|
||||
|
||||

|
||||
|
||||
## Getting Started
|
||||
|
||||
### Create .env file
|
||||
|
||||
1. Create a `.env` file.
|
||||
Create a `.env` file.
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
2. Define required API keys in your `.env` file.
|
||||
Set the required API keys in your `.env` file.
|
||||
|
||||
<!--
|
||||
Setup instruction auto-generated by `langgraph template lock`. DO NOT EDIT MANUALLY.
|
||||
@@ -66,98 +58,143 @@ OPENAI_API_KEY=your-api-key
|
||||
End setup instructions
|
||||
-->
|
||||
|
||||
### LangGraph Studio
|
||||
If you want to test the memory service locally, [install the LangGraph Studio desktop app](https://github.com/langchain-ai/langgraph-studio?tab=readme-ov-file#download).
|
||||
|
||||
If you want to test locally, [install the LangGraph Studio desktop app](https://github.com/langchain-ai/langgraph-studio?tab=readme-ov-file#download).
|
||||
If you want to test in the cloud, [follow these instructions to deploy this repository to LangGraph Cloud](https://langchain-ai.github.io/langgraph/cloud/) and use Studio in your browser.
|
||||
|
||||
If you want to test in the cloud, [follow these instructions to deploy this repository to LangGraph Cloud](https://langchain-ai.github.io/langgraph/cloud/) and open Studio in your browser.
|
||||
Open this repository in LangGraph studio and navigate to the `chatbot` graph.
|
||||
|
||||
Open this repository in LangGraph studio.
|
||||
|
||||
In LangGraph Studio, you can set your `user_id`, `model`, or other configurations.
|
||||
Optionally, you can set your `user_id`, `model`, or other configurations directly in the Studio UI.
|
||||
|
||||

|
||||
|
||||
Navigate to the "`chatbot`" graph and have a conversation with it!
|
||||
|
||||
Try sending some messages saying your name and other things the bot should remember.
|
||||
|
||||
Wait ~10-20 seconds for many memories to be created and saved.
|
||||
Wait ~10-20 seconds for memories to be created and saved.
|
||||
|
||||
Then, create a *new* thread using the `+` icon.
|
||||
Create a *new* thread using the `+` icon.
|
||||
|
||||
Then chat with the bot again - if you've completed your setup correctly, the bot should now have access to the memories you've saved!
|
||||
Then chat with the bot again.
|
||||
|
||||
The bot should have access to the memories you've saved, and will use them to personalize its responses.
|
||||
|
||||
## How it works
|
||||
|
||||
There are several problems to solve when building a memory service:
|
||||
|
||||
1. What should each memory contain?
|
||||
2. How should memories be updated?
|
||||
3. How frequently should memories be updated or created?
|
||||
4. Where should memories be stored?
|
||||
5. How to call the memory service from our application?
|
||||
|
||||
We'll address these challenges below, and explain how this LangGraph template approaches them.
|
||||
|
||||
### Memory Schema
|
||||
|
||||
The memory schema defines what each memory will contain.
|
||||
|
||||
By default, this template uses two memory schemas: `User` and `Note`. Both are JSON schemas.
|
||||
|
||||
The schemas are defined in [memory_graph/configuration.py](./src/memory_graph/configuration.py).
|
||||
|
||||
The `User` schema is used to store a single profile for a user with a set of predefined properties (e.g., name, age, interests).
|
||||
|
||||
The `Note` schema is more flexible, containing a `context` and `content` field to capture any type of information as a memory.
|
||||
|
||||
These schemas are customizable! You can create new schemas, or add / remove properties as needed for your application.
|
||||
|
||||
### Memory Updates
|
||||
|
||||
These memory schemas need to be updated with new information over time.
|
||||
|
||||
The `User` schema is a single JSON object.
|
||||
|
||||
We want to update it with new information about the user as the conversation progresses.
|
||||
|
||||
Each `Note`, in contrast, is captured in a list.
|
||||
|
||||
We want the flexibility to update existing `Note` schemas or update the list with new ones.
|
||||
|
||||
We use the [`trustcall` library](https://github.com/hinthornw/trustcall) to do both of these types of updates.
|
||||
|
||||
This is a library that we created for updating JSON schemas via a LLM.
|
||||
|
||||
These updates are performed in [memory_graph/graph.py](./src/memory_graph/graph.py).
|
||||
|
||||
The `memory_graph` saves both types of memories.
|
||||
|
||||
We can see the graph here in the LangGraph Studio, with a branch for each of the defined memory schemas:
|
||||
|
||||
* `handle_patch_memory` is for `User` schema memories.
|
||||
* `handle_insert_memory` is for `Note` schema memories.
|
||||
|
||||

|
||||
|
||||
### Memory Scheduling
|
||||
|
||||
Memory updates need to be scheduled to avoid duplicate processing.
|
||||
|
||||
Ideally, we want to wait until a chat is complete before we create memories.
|
||||
|
||||
But, we don't know when a chat session will end.
|
||||
|
||||
So, we wait a pre-determined interval before invoking the memory graph to memories to the storage layer.
|
||||
|
||||
If the chatbot makes a call second time within that interval, the initial memory is cancelled.
|
||||
|
||||
Scheduling is handled by the LangGraph SDK's `after_seconds` parameter.
|
||||
|
||||
We call the `memory_graph` from our application (e.g., `chatbot`) using the LangGraph SDK in [chatbot/graph.py](./src/chatbot/graph.py).
|
||||
|
||||

|
||||
|
||||
### Memory Storage
|
||||
|
||||
The LangGraph API comes with a built-in memory storage layer that can be used to store and retrieve information across threads.
|
||||
|
||||
Studio useds the LangGraph API at the backend, packaging the code in this repository with the storage layer.
|
||||
|
||||
In Studio, you can see the `Memories` button above your graph with any memories created and saved to the storage layer.
|
||||
|
||||
The storage layer is shown in the above diagram in red.
|
||||
|
||||
The central points are that it:
|
||||
|
||||
1. It is accessible to both the `chatbot` and the `memory_graph` in all nodes.
|
||||
2. It provides an interface for storing (`put` method) and retrieving (`search` method) memories in a namespaced manner.
|
||||
|
||||
Learn more about the Memory Storage layer [here](https://langchain-ai.github.io/langgraph/how-tos/memory/shared-state/).
|
||||
|
||||
### Chatbot Graph
|
||||
Importantly, the memory storage layer is namespaced by a tuple; in this case, we use the `user_id` as well as the schema name.
|
||||
|
||||
The `chatbot` graph, defined in [graph.py](./src/chatbot/graph.py), has two nodes, `bot` and `schedule_memories`.
|
||||
In addition, the memory storage layer is accessible to both the `chatbot` and the `memory_graph` in all graph nodes.
|
||||
|
||||
The `chatbot` is invoked with a `user_id` supplied by configuration.
|
||||
|
||||
The `bot` node uses the `user_id` to fetch any existing memories for that user from the `Memory Storage` layer.
|
||||
|
||||
These fetched memories are added to the system prompt of the chatbot to personalize the responses.
|
||||
|
||||
The `schedule_memories` node is run after the `bot` node.
|
||||
|
||||
It is responsible for scheduling long-term memory creation based upon the chatbot's updated interaction with the user.
|
||||
|
||||
It uses the LangGraph SDK to call the `memory_graph`, suppling the chatbot's interaction with the user.
|
||||
|
||||
### Memory Graph
|
||||
|
||||
The `memory_graph` graph, defined in [graph.py](./src/memory_graph/graph.py) incoperates two different concepts:
|
||||
|
||||
(1) We can define a schema for each of the types of memories we want to store.
|
||||
|
||||
(2) We can update these memories in different ways using the [`trustcall` library](https://github.com/hinthornw/trustcall).
|
||||
|
||||
The schema for each memory type is defined in [configuration.py](./src/memory_graph/configuration.py).
|
||||
|
||||
The default schemas are `User` and `Note`.
|
||||
|
||||
The `User` schema is used to store a single profile for a user, such as their name, age, and interests.
|
||||
|
||||
We'll store a single JSON schema that can be updated with new information as the conversation progresses.
|
||||
|
||||
The `Note` schema is used to store specific events or notes about the user's interactions with the chatbot.
|
||||
|
||||
We'll store a list of JSON schemas that can be updated or added to as the conversation processes.
|
||||
|
||||
The [`trustcall` library](https://github.com/hinthornw/trustcall) handles writing and updating either of these schemas.
|
||||
This diagram shows how these pieces fit together:
|
||||
|
||||

|
||||
|
||||
The `memory_graph` save both types of memories to the `Memory Storage` layer, namespaced by the `user_id` and the schema name.
|
||||
### Calling the Memory Service
|
||||
|
||||
We can see the graph here in the LangGraph Studio, with a branch for each memory schemas.
|
||||
Studio uses the LangGraph API as its backend, packaging the specified code repository with the storage layer.
|
||||
|
||||

|
||||
The `langgraph.json` file is used to configure the LangGraph API specifies the graphs to be run in Studio:
|
||||
|
||||
## Philosophy
|
||||
```json
|
||||
"graphs": {
|
||||
"chatbot": "./src/chatbot/graph.py:graph",
|
||||
"memory_graph": "./src/memory_graph/graph.py:graph"
|
||||
},
|
||||
```
|
||||
|
||||
### Separation of Concerns
|
||||
The chatbot can directly access all stored memories when it's preparing responses for the user.
|
||||
|
||||
This separation of concerns between the application logic (chatbot) and the memory processing (the memory graph) provides advantages:
|
||||
You can see this in the in the `bot` node in [chatbot/graph.py](./src/chatbot/graph.py):
|
||||
|
||||
```python
|
||||
items = await store.asearch(namespace)
|
||||
```
|
||||
|
||||
To schedule creation of new memories, the chatbot can use the LangGraph SDK to access the memory graph.
|
||||
|
||||
This is done in the `schedule_memories` node in [chatbot/graph.py](./src/chatbot/graph.py)
|
||||
|
||||
This passes the chatbot's interaction with the user along with the scheduling parameter, `after_seconds`, to the `memory_graph`.
|
||||
|
||||

|
||||
|
||||
## Benefits
|
||||
|
||||
The separation of concerns between the application logic (chatbot) and the memory (the memory graph) a few advantages:
|
||||
|
||||
(1) minimal overhead by removing memory creation logic from the hotpath of the application (e.g., no latency cost for memory creation)
|
||||
|
||||
@@ -165,26 +202,10 @@ This separation of concerns between the application logic (chatbot) and the memo
|
||||
|
||||
(3) memory graph can be updated and / or hosted (as a service) independently of the application (chatbot)
|
||||
|
||||
Here is a schematic of the interaction pattern:
|
||||
|
||||

|
||||
|
||||
### Scheduling
|
||||
|
||||
Scheduling is handled by the LangGraph API's `after_seconds` parameter.
|
||||
|
||||
This is the intuition: we want to wait until a thread is "complete" before we write memories to the storage layer.
|
||||
|
||||
We don't know when a chat will end.
|
||||
|
||||
So, we wait a pre-determined interval before invoking the memory graph to memories to the storage layer.
|
||||
|
||||
If the chatbot makes a call second time within that interval, the memory run is cancelled to avoid duplicate processing of a thread.
|
||||
|
||||
This cartoon highlights the concept: requests to call the `memory_graph` are delayed for some period of time.
|
||||
|
||||
If any newer requests come in, the initial request is cancelled to avoid duplicate processing the same interaction.
|
||||
|
||||

|
||||
|
||||
## How to evaluate
|
||||
|
||||
Memory management can be challenging to get right. To make sure your memory_types suit your applications' needs, we recommend starting from an evaluation set, adding to it over time as you find and address common errors in your service.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 169 KiB |
Reference in New Issue
Block a user