Гайд · TNWS AI

Как сохранить историю диалога LangChain по thread_id

LangChain 1.xPythonopenai:gpt-5.5ChatGPT#LangChain#Python#AI-агенты
5 мин—

InMemorySaver, одинаковый thread_id для продолжения и отдельный ID для другого пользователя без смешивания бесед.

Задача и применимость

Русскоязычный запрос: «как включить память LangChain checkpointer thread_id». Проверка официальной документации LangChain — 19 сентября 2026 года. LangChain 1.x Python и LangGraph checkpointer; InMemorySaver подходит для локальной демонстрации, для устойчивого production хранения нужен поддерживаемый постоянный backend.

Краткосрочная память агента хранится в его состоянии через checkpointer. Для продолжения беседы передают config={"configurable":{"thread_id":...}} с тем же идентификатором. Состояния разных threads разделены; InMemorySaver хранит данные в памяти процесса и не является надёжным долговременным хранилищем после рестарта.

Порядок действий

  1. Создайте агент с checkpointer=InMemorySaver() в тестовом окружении.
  2. Для первого пользователя сформируйте непредсказуемый серверный thread_id и свяжите его с подтверждённой учётной записью.
  3. Выполните первое invoke с именем, затем второе invoke с вопросом «как меня зовут?» и тем же config.
  4. Повторите вопрос с новым thread_id другого пользователя; имя первого не должно появиться.
  5. Перезапустите процесс для проверки, что локальная память не сохраняется; для production выберите persistent saver.

Пример ниже предназначен для демонстрационного окружения: установите соответствующий пакет интеграции, настройте ключ через секреты сервера и убедитесь, что модель доступна вашему аккаунту. Если доступ к указанному model ID отсутствует, выберите поддерживаемую модель со сходными возможностями и заново проверьте работу именно на ней. Ни один пример не содержит действующего API-ключа и не разрешает обход ограничений провайдера.

Готовый шаблон на Python

from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver

agent = create_agent(model="openai:gpt-5.5", tools=[],
                     checkpointer=InMemorySaver())
alice = {"configurable": {"thread_id": "demo-alice"}}
bob = {"configurable": {"thread_id": "demo-bob"}}
agent.invoke({"messages": [{"role": "user", "content":
    "Меня зовут Аня."}]}, config=alice)
answer = agent.invoke({"messages": [{"role": "user", "content":
    "Как меня зовут?"}]}, config=alice)
print(answer["messages"][-1].content)
# Важный тест изоляции: с config=bob имя Аня неизвестно.

Конкретные входные и ожидаемые данные

Вход: в thread demo-alice человек сообщает «Меня зовут Аня», затем спрашивает имя. Ожидается ответ с «Аня». В thread demo-bob с единственным вопросом «как меня зовут?» правильное поведение — признать отсутствие данных; если ответ называет Аню, приложение нарушило изоляцию.

Оценивать стоит не красоту формулировки, а проверяемое выполнение задачи. Сохраните исходный текст, ID пользователя или теста и ожидаемое значение отдельно от ответа модели. Если пример выдаёт неверный факт, разберите данные на входе и состояние инструмента до изменения промпта: иначе можно замаскировать ошибку инфраструктуры удачной перефразировкой.

Диагностика и границы решения

Thread ID — не просто удобный ярлык для интерфейса, а ключ к сохранённому состоянию беседы. Если клиент может произвольно прислать чужой ID и сервер не проверяет принадлежность, память становится источником утечек персональных данных. Поэтому выдавайте ID из защищённой серверной сессии и проверяйте, что он принадлежит именно текущему пользователю. InMemorySaver позволяет быстро протестировать причинно-следственную цепочку сообщений, но рестарт приложения потеряет данные; несколько процессов также не должны предполагать общую память. Долговременная информация профиля пользователя — отдельная задача, которую не следует решать бесконечным добавлением сообщений в thread. Контекстное окно модели ограничено: длительная история может потребовать summarization или удаления сообщений с явным контролем потери фактов. Для теста задайте и положительный контроль, и отрицательный на новом thread; только проверка первого скрывает опасную путаницу пользователей. Не добавляйте секреты в историю ради удобства: сообщение может попасть в следующие prompts и в систему трассировки.

Контрольный эксперимент

Составьте матрицу доступа из двух пользователей и двух threads: A обращается к A, B к B, A пытается указать ID B, B пытается указать ID A. Последние два случая должны отклоняться ещё до обращения к агенту. Если пользователь просит «забудь имя», нужен отдельный процесс удаления/редактирования сохранённых данных; простая просьба в сообщении не удаляет автоматически запись checkpointer. При росте истории проверяйте, что старый срок возврата из прежнего разговора не вытесняет свежую политику из базы знаний. Состояние — память о разговоре, не авторитетный источник актуальных правил. При переключении на persistent saver протестируйте восстановление после перезапуска и аварии в середине tool call, а также истечение срока хранения и удаление по запросу пользователя. Модель может перефразировать имя, поэтому оцените фактическое значение, не точный текст ответа.

Дополнительный проверочный сценарий

Сама память не различает «пользователь утверждает» и «подтверждено системой», если вы не зададите явные правила. Пользователь может сказать «мой заказ уже оплачен», но статус оплаты надо получить из платежного источника, а не из старого сообщения в thread. Для каждого сохранённого факта держите происхождение: сообщение пользователя, ответ инструмента или проверенная запись. Если статус изменился, повторно получите его на текущем шаге, не копируйте из истории. Проверьте сценарий, где пользователь А упоминает имя Б и спрашивает позже «как меня зовут?»: агенту нельзя некритично считать любое имя в истории именем владельца. Хранение контекста повышает удобство, но не создаёт источник истины и систему прав.

Критерии результата

  • Одинаковый thread_id сохраняет контекст двух вызовов.
  • Другой thread_id не раскрывает Аню.
  • Сервер запрещает подстановку чужого thread_id.
  • Ограничения InMemorySaver после рестарта отражены в архитектуре.

При провале критерия помечайте задачу незавершённой. Корректный HTTP-ответ от провайдера не доказывает истинность результата, а удачный результат локального теста не гарантирует ту же доступность модели или сервисов в вашем рабочем окружении.

Типичные ошибки и что не делать

  • Использовать один ID для всех пользователей.
  • Принимать thread_id из клиента без проверки владельца.
  • Считать InMemorySaver постоянной БД.
  • Хранить пароль или секрет в сообщениях.

Не отправляйте персональные сведения и секреты в инструмент трассировки или тестовый аккаунт без оценки права доступа и политики хранения. Сначала добейтесь правильного ответа на небольшом наборе положительных и отрицательных примеров, затем подключайте полноценный контент или базу данных.

FAQ

Что связывает два сообщения?

Один и тот же thread_id при настроенном checkpointer.

Сохранится ли InMemorySaver после рестарта?

Нет, это память процесса.

Является ли thread памятью обо всех сессиях пользователя?

Нет, это контекст конкретного потока.

Официальные источники

Частые вопросы

Что связывает два сообщения?

Один и тот же thread_id при настроенном checkpointer.

Сохранится ли InMemorySaver после рестарта?

Нет, это память процесса.

Является ли thread памятью обо всех сессиях пользователя?

Нет, это контекст конкретного потока.

Читайте также

Комментарии

Пока тихо. Скажите первое слово