Files
gh-hiroshi75-protografico-p…/skills/langgraph-master/03_memory_management_checkpointer.md
2025-11-29 18:45:58 +08:00

225 lines
4.9 KiB
Markdown

# Checkpointer
Implementation details for saving and restoring state.
## Overview
Checkpointer implements the `BaseCheckpointSaver` interface and is responsible for state persistence.
## Checkpointer Implementations
### 1. MemorySaver (For Experimentation & Testing)
Saves checkpoints in memory:
```python
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
graph = builder.compile(checkpointer=checkpointer)
# All data is lost when the process terminates
```
**Use Case**: Local testing, prototyping
### 2. SqliteSaver (For Local Development)
Saves to SQLite database:
```python
from langgraph.checkpoint.sqlite import SqliteSaver
# File-based
checkpointer = SqliteSaver.from_conn_string("checkpoints.db")
# Or from connection object
import sqlite3
conn = sqlite3.connect("checkpoints.db")
checkpointer = SqliteSaver(conn)
graph = builder.compile(checkpointer=checkpointer)
```
**Use Case**: Local development, single-user applications
### 3. PostgresSaver (For Production)
Saves to PostgreSQL database:
```python
from langgraph.checkpoint.postgres import PostgresSaver
from psycopg_pool import ConnectionPool
# Connection pool
pool = ConnectionPool(
conninfo="postgresql://user:password@localhost:5432/db"
)
checkpointer = PostgresSaver(pool)
graph = builder.compile(checkpointer=checkpointer)
```
**Use Case**: Production environments, multi-user applications
## BaseCheckpointSaver Interface
All checkpointers implement the following methods:
```python
class BaseCheckpointSaver:
def put(
self,
config: RunnableConfig,
checkpoint: Checkpoint,
metadata: dict
) -> RunnableConfig:
"""Save a checkpoint"""
def get_tuple(
self,
config: RunnableConfig
) -> CheckpointTuple | None:
"""Retrieve a checkpoint"""
def list(
self,
config: RunnableConfig,
*,
before: RunnableConfig | None = None,
limit: int | None = None
) -> Iterator[CheckpointTuple]:
"""Get list of checkpoints"""
```
## Custom Checkpointer
Implement your own persistence logic:
```python
from langgraph.checkpoint.base import BaseCheckpointSaver
class RedisCheckpointer(BaseCheckpointSaver):
def __init__(self, redis_client):
self.redis = redis_client
def put(self, config, checkpoint, metadata):
thread_id = config["configurable"]["thread_id"]
checkpoint_id = checkpoint["id"]
key = f"checkpoint:{thread_id}:{checkpoint_id}"
self.redis.set(key, serialize(checkpoint))
return config
def get_tuple(self, config):
thread_id = config["configurable"]["thread_id"]
# Retrieve the latest checkpoint
# ...
def list(self, config, before=None, limit=None):
# Return list of checkpoints
# ...
```
## Checkpointer Configuration
### Namespaces
Share the same checkpointer across multiple graphs:
```python
checkpointer = MemorySaver()
graph1 = builder1.compile(
checkpointer=checkpointer,
name="graph1" # Namespace
)
graph2 = builder2.compile(
checkpointer=checkpointer,
name="graph2" # Different namespace
)
```
### Automatic Propagation
Parent graph's checkpointer automatically propagates to subgraphs:
```python
# Set only on parent graph
parent_graph = parent_builder.compile(checkpointer=checkpointer)
# Automatically propagates to child graphs
```
## Checkpoint Management
### Deleting Old Checkpoints
```python
# Delete after a certain period (implementation-dependent)
import datetime
cutoff = datetime.datetime.now() - datetime.timedelta(days=30)
# Implementation example (SQLite)
checkpointer.conn.execute(
"DELETE FROM checkpoints WHERE created_at < ?",
(cutoff,)
)
```
### Optimizing Checkpoint Size
```python
class State(TypedDict):
# Avoid large data
messages: Annotated[list, add_messages]
# Store references only
large_data_id: str # Actual data in separate storage
def node(state: State):
# Retrieve large data from external source
large_data = fetch_from_storage(state["large_data_id"])
# ...
```
## Performance Considerations
### Connection Pool (PostgreSQL)
```python
from psycopg_pool import ConnectionPool
pool = ConnectionPool(
conninfo=conn_string,
min_size=5,
max_size=20
)
checkpointer = PostgresSaver(pool)
```
### Async Checkpointer
```python
from langgraph.checkpoint.postgres import AsyncPostgresSaver
async_checkpointer = AsyncPostgresSaver(async_pool)
# Async execution
async for chunk in graph.astream(input, config):
print(chunk)
```
## Summary
Checkpointer determines how state is persisted. It's important to choose the appropriate implementation for your use case.
## Related Pages
- [03_memory_management_persistence.md](03_memory_management_persistence.md) - How to use persistence
- [03_memory_management_store.md](03_memory_management_store.md) - Differences from long-term memory