Межсессионное хранилище LangChain — Store
Checkpointer решает проблему «памяти в рамках одного диалога». Но если вам нужно обмениваться данными между разными диалогами — например, пользовательскими предпочтениями или прогрессом обучения — вам нужно использоватьStore。
Checkpointer против Store
| Измерение | Checkpointer | Store |
|---|---|---|
| Область действия | Один поток диалога (thread_id) | По всем потокам диалога |
| Тип данных | Снимок состояния агента (управляется автоматически) | Произвольные данные ключ-значение (управляются вручную) |
| Типичные случаи использования | Память многоходового диалога | Пользовательские предпочтения, база знаний, конфигурация |
| Организация данных | thread_id → checkpoint | (namespace, key) → value |
Основные операции Store
Использование StoreNamespace + keyдля организации данных в иерархической структуре:
Пример
store = InMemoryStore()
# Запись данных: put(namespace, key, value)
# namespace — это кортеж, key — строка, value — словарь
store.put(
("users", "user_001"), # Пространство имён
"preferences", # Ключ
{ # Значение
"theme": "dark",
"language": "zh-CN",
"level": "Новичок",
}
)
store.put(
("users", "user_001"),
"progress",
{
"completed_courses": ["HTML Basics", "Python Basics"],
"total_hours": 35,
}
)
# Чтение данных: get(namespace, key)
prefs = store.get(("users", "user_001"), "preferences")
print(f"Настройки: {prefs.value}")
progress = store.get(("users", "user_001"), "progress")
print(f"Прогресс обучения: {progress.value}")
# Поиск данных: search(namespace)
all_user_data = store.search(("users", "user_001"))
print(f"\n"Все данные пользователя ({len(all_user_data)} элементов):")
for item in all_user_data:
print(f" {item.key}: {item.value}")
# Удаление данных: delete(namespace, key)
store.delete(("users", "user_001"), "preferences")
deleted = store.get(("users", "user_001"), "preferences")
print(f"\n"После удаления: {deleted}") # None
Вывод:
Preferences: {'theme': 'dark', 'language': 'zh-CN', 'level': '入门'}
Learning progress: {'completed_courses': ['HTML 基础', 'Python 基础'], 'total_hours': 35}
用户的所有数据 (2 项):
preferences: {'theme': 'dark', 'language': 'zh-CN', 'level': '入门'}
progress: {'completed_courses': ['HTML 基础', 'Python 基础'], 'total_hours': 35}
After deletion: None
Использование Store в агенте
Передайте Store в create_agent(), и все инструменты в Agent смогут получить к нему доступ через InjectedStore:
Пример
load_dotenv()
from typing import Annotated
from langgraph.store.base import BaseStore
from langgraph.store.memory import InMemoryStore
from langchain.tools import tool, InjectedStore
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage
# Создайте Store и предварительно заполните данные
store = InMemoryStore()
store.put(("example", "courses"), "catalog", {
"Учебник по основам Python3": {"price": "Бесплатно", "hours": 20, "level": "Начальный"},
"Анализ данных на Python": {"price": "Для участников", "hours": 30, "level": "Продвинутый"},
"Объектно-ориентированное программирование на Java": {"price": "Бесплатно", "hours": 25, "level": "Продвинутый"},
})
store.put(("example", "users"), "user_vip_001", {
"name": "Сяо Мин",
"membership": "VIP",
"joined": "2024-01-15",
})
@tool
def query_course_info(
course_name: str,
store: Annotated[BaseStore, InjectedStore()],
) -> str:
"""Запрос подробной информации о курсах на учебном сайте EXAMPLE.
Аргументы:
course_name: Название курса
"""
item = store.get(("example", "courses"), "catalog")
catalog = item.value if item else {}
if course_name in catalog:
info = catalog[course_name]
return (
f"《{course_name}》 - Цена: {info['price']},"
f"Продолжительность: {info['hours']} hours, Сложность: {info['level']}"
)
return f"Курс 《{course_name}》 не найден"
@tool
def get_user_membership(
user_id: str,
store: Annotated[BaseStore, InjectedStore()],
) -> str:
"""Запрос информации о членстве пользователя.
Аргументы:
user_id: ID пользователя
"""
item = store.get(("example", "users"), user_id)
if item is None:
return f"Пользователь {user_id} не найден"
user = item.value
return (
f"Пользователь {user['name']}, участник {user['membership']},"
f"Дата регистрации {user['joined']}"
)
model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)
agent = create_agent(
model=model,
tools=[query_course_info, get_user_membership],
store=store,
system_prompt="Вы — консультант по курсу для EXAMPLE.",
)
# Запрос информации о курсе (данные поступают из Store)
result = agent.invoke({
"messages": [HumanMessage(content="Сколько стоит Python3 Basics Tutorial?")]
})
print(f"Запрос курса: {result['messages'][-1].content}")
# Запрос информации о пользователе (данные поступают из Store)
result = agent.invoke({
"messages": [HumanMessage(content="Помогите найти информацию о пользователе user_vip_001")]
})
print(f"Запрос пользователя: {result['messages'][-1].content}")
Вывод:
Course query: 《Python3 基础教程》是免费的,学习时长约20小时,难度为入门级别。 User query: 用户小明是 VIP 会员,注册日期为 2024年1月15日。
Персистентность хранилища
Данные InMemoryStore теряются после перезапуска программы. Для производственных сред можно использовать персистентные решения, такие как PostgresStore:
Пример
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()
# Производственная среда (требуется PostgreSQL)
# from langgraph.store.postgres import PostgresStore
# store = PostgresStore.from_conn_string("postgresql://...")
Рекомендации по использованию хранилища
| Сценарий | пример пространства имён | пример ключа | Описание |
|---|---|---|---|
| Пользовательские предпочтения | ("users", user_id) | preferences | Тема, язык, настройки уведомлений |
| Прогресс обучения | ("users", user_id) | прогресс | Пройденные курсы, продолжительность обучения |
| База знаний | ("kb", collection) | doc_id | Документы, FAQ, информация о продукте |
| Резюме разговоров | ("sessions", thread_id) | summary | Резюме длинных разговоров для использования в сценариях за пределами Checkpointer |
Другие расширенияCheckpointer отвечает за «где находится разговор», а Store — за «кто пользователь, что он знает и что ему нравится». Только используя оба вместе, можно построить интеллектуального агента с постоянной памятью.