Память и состояние агента на практике

От теории к коду: реализуем простую память агента с обрезкой истории и хранением фактов — то, что в настоящем агенте держит контекст между шагами.

Состояние агента — то, что он помнит прямо сейчас: усечённая история диалога (краткосрочная память) плюс набор сохранённых фактов (зачаток долгосрочной).

Что должна уметь память

  • добавлять реплики (роль + текст) и хранить только последние — чтобы влезть в окно;
  • сохранять отдельные факты «ключ → значение» надолго;
  • выдавать текущий контекст для передачи модели.

Класс памяти

class AgentMemory:
    def __init__(self, max_turns=3):
        self.history = []          # краткосрочная: список (роль, текст)
        self.max_turns = max_turns # сколько реплик держим
        self.facts = {}            # долгосрочная: ключ -> значение

    def add(self, role, text):
        self.history.append((role, text))
        # обрезаем до последних max_turns реплик (эмуляция окна)
        self.history = self.history[-self.max_turns:]

    def remember(self, key, value):
        self.facts[key] = value

    def context(self):
        return "\n".join(f"{r}: {t}" for r, t in self.history)


mem = AgentMemory(max_turns=3)
mem.add("user", "Меня зовут Аня")
mem.remember("имя", "Аня")          # важный факт — в долгосрочную память
mem.add("agent", "Приятно познакомиться, Аня")
mem.add("user", "Столица Франции?")
mem.add("agent", "Париж")

print("Краткосрочный контекст (последние 3 реплики):")
print(mem.context())
print("---")
print("Долгосрочный факт 'имя':", mem.facts["имя"])

Вывод:

Краткосрочный контекст (последние 3 реплики):
agent: Приятно познакомиться, Аня
user: Столица Франции?
agent: Париж
---
Долгосрочный факт 'имя': Аня

Важная деталь: первая реплика «Меня зовут Аня» выпала из краткосрочной истории (окно — 3 реплики), но имя сохранилось в долгосрочных фактах. Так и работает разделение памяти: сырой диалог обрезается, а важное выносится в надёжное хранилище.

Почему обрезка важна

Если не ограничивать историю, в длинном диалоге она перерастёт контекстное окно — модель либо обрежет её непредсказуемо, либо вызов вообще не пройдёт. Управляемая обрезка (или суммаризация) держит размер под контролем и оставляет самое свежее.

Состояние сверх диалога

Память — частный случай состояния агента. Кроме истории, агент может хранить: счётчик шагов, промежуточные результаты, список выполненных подзадач, флаг «нужен человек». Аккуратная работа с состоянием — то, что отличает рабочего агента от хрупкого скрипта; именно поэтому фреймворки вроде LangGraph строятся вокруг явного состояния (раздел 6).

state = {"step": 0, "done_subtasks": [], "need_human": False}

def do_subtask(state, name):
    state["step"] += 1
    state["done_subtasks"].append(name)
    return state

state = do_subtask(state, "собрать данные")
state = do_subtask(state, "посчитать")
print("Шагов сделано:", state["step"])
print("Выполнено:", state["done_subtasks"])
print("Нужен человек:", state["need_human"])

Вывод:

Шагов сделано: 2
Выполнено: ['собрать данные', 'посчитать']
Нужен человек: False

Итог

  • Память агента = усечённая краткосрочная история + долгосрочные факты «ключ-значение».
  • Обрезка истории удерживает контекст в пределах окна; важное выносится в долгосрочное хранилище.
  • Память — часть состояния агента; явное состояние (шаги, подзадачи, флаги) делает агента надёжнее.
Проверьте себя
1. Что произошло с репликой «Меня зовут Аня» при max_turns=3?
AОна удалена навсегда из всей памяти
BОна выпала из краткосрочной истории, но имя сохранилось в долгосрочных фактах
CОна осталась в истории, обрезка не сработала
DОна вызвала ошибку переполнения
2. Зачем обрезать (или суммаризировать) краткосрочную историю?
AЧтобы ускорить запись в словарь
BЧтобы история не переросла контекстное окно модели
CЧтобы спрятать данные от пользователя
DЭто требование Python
3. Что, помимо истории диалога, относится к состоянию агента?
AТолько текст вопроса
BСчётчик шагов, промежуточные результаты, список подзадач, флаги вроде «нужен человек»
CИсходный код инструментов
DВерсия модели
Поддержать проект