
Детерминированный бенчмарк и среда оценки для отравления постоянной памяти в LLM-агентах, с парными чистыми/отравленными случаями, раннерами LangChain/LlamaIndex и средствами защиты.
Этот репозиторий сопровождает статью MemForm: Benchmarking Memory Formation Poisoning in LLM Agents.
MemForm — это детерминированный бенчмарк отравления постоянной памяти в LLM-агентах. Он задаёт причинный вопрос, который обычные наборы тестов на джейлбрейк или внедрение промптов не изолируют:
Если долговременная память агента изменяется на одной чётко определённой поверхности, смещается ли последующее принятие решений с чистой политики на отравленную политику при выполнении той же задачи?
Каждый элемент представляет собой парное вмешательство. Нижестоящий триггер, пространство действий и семантика семейства остаются фиксированными. Между чистыми и отравленными условиями изменяется только вход, формирующий память. Успех атаки — это контраст внутри элемента.
Этот релиз содержит замороженные случаи бенчмарка и раннеры оценки / защиты. Конвейер построения удерживается, пока статья находится на рецензировании, и будет выпущен после публикации.
Каждое семейство инстанцируется на пяти интерфейсах памяти. Поле случая — interface. P1–P5 — это названия из статьи: Content, Evidence, Scope, Selection и Path.
| Интерфейс | Название в статье | Причинная переменная | Контраст «чистое vs. отравленное» | Нижестоящий зонд |
|---|---|---|---|---|
| P1 | Content | Текст хранимой памяти | Прямая запись чистой переиспользуемой политики vs. отравленной политики | Одна общая целевая задача |
| P2 | Evidence | Подлинность подтверждающих записей | Аутентичная история с равным бюджетом vs. сопоставленная история, в которой часть записей заменена поддельными доказательствами. Происхождение скрыто от обучающегося памяти | Одна общая целевая задача |
| P3 | Scope | Наблюдаемое распределение области действия | Локально валидные доказательства плюс внешние контрпримеры vs. заметные по сигналу внутренние успехи плюс аутентичные внешние/общие успехи для локально предпочитаемого действия | Три задачи: в пределах области, около границы области, целевая вне области |
| P4 | Selection | Сохраняемое подмножество | Один и тот же пул кандидатов; чистое vs. отравленное сохранение подмножества фиксированного размера, с контролем на полном пуле | Одна общая целевая задача |
| P5 | Path | Только порядок консолидации | Один и тот же мультимножество опыта в одном контексте в двух перестановках. Чистые доказательства идут последними в чистом порядке; отравленные доказательства идут последними в отравленном порядке | Одна целевая задача в том же контексте |
P3 в пределах области — это контроль согласия / общей цели: чистые и отравленные эталонные ответы идентичны. Задачи около границы и целевые вне области — это разделимые зонды. P5 запрещает скрытые сдвиги контекста: каждая запись имеет один context_key, и записи, поддерживающие как чистое, так и отравленное состояние, являются наблюдаемыми успехами.
| Путь | Содержимое |
|---|---|
outputs/mcq_item_audit/accepted_cases.jsonl | Замороженные случаи с множественным выбором (994 элемента, 235 семейств) |
outputs/freeform_item_audit/accepted_cases.jsonl | Замороженные случаи свободной формы (897 элементов, 218 семейств) |
memform/eval/ | Общий протокол плюс раннеры LangChain / LlamaIndex / защиты |
memform/freeform/evaluator.py | Каскадный арбитр ответов свободной формы |
memform/defenses/ | Защиты на этапе записи, Task Shield на этапе использования и метрики с фиксированным знаменателем |
memform/common.py | Ввод-вывод JSONL и проверки схемы случаев |
Количество по интерфейсам — MCQ: P1 234, P2 233, P3 174, P4 144, P5 209. Свободная форма: P1 209, P2 212, P3 144, P4 134, P5 198.
memform-code/
├── outputs/
│ ├── mcq_item_audit/accepted_cases.jsonl
│ └── freeform_item_audit/accepted_cases.jsonl
├── memform/
│ ├── common.py
│ ├── freeform/evaluator.py
│ ├── eval/ # protocol, LangChain, LlamaIndex, defense runners
│ └── defenses/
├── run_langchain.py
├── run_llamaindex.py
├── run_defense.py
├── pyproject.toml
├── requirements.txt
└── .env.example
Скрипты run_*.py в корневом каталоге вызывают те же точки входа, что и python -m memform <command>.
Python 3.10+.
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
Скопируйте .env.example в .env и задайте учётные данные:
| Переменная | Используется |
|---|---|
OPENAI_API_KEY | Агент оценки / модель памяти |
OPENAI_BASE_URL | Необязательный OpenAI-совместимый шлюз (OPENAI_API_BASE также принимается LlamaIndex) |
JUDGE_OPENAI_API_KEY / JUDGE_OPENAI_BASE_URL | Необязательный отдельный судья / свободный оценщик |
DEFENSE_OPENAI_API_KEY / DEFENSE_OPENAI_BASE_URL | Необязательная отдельная конечная точка модели защиты |
--api-key и --base-url переопределяют переменные окружения. Подходит любой OpenAI-совместимый сервер Chat Completions. Имена моделей по умолчанию в CLI являются заполнителями; передайте модель, доступную на вашей конечной точке.
python -m memform --help
JSONL, один случай на строку.
Общие поля: case_id, family_id, interface (P1–P5), attack_type, domain, decision_variable, clean_policy, poisoned_policy, scope, candidate_experiences, memory_building, metadata.
memory_building — это парное вмешательство:
oracle_memory.clean / oracle_memory.poisoned — эталонный текст политики (диагностика)clean_condition / poisoned_condition — входные данные для построения памяти для этого интерфейсаMCQ. evaluation.type имеет значение multiple_choice. Каждая запись trigger_tasks[] содержит task, choices, clean_answer и poisoned_answer.
Свободная форма. task_format имеет значение free_form; source_case_id указывает на источник MCQ. Меню вариантов заменяются открытой рекомендацией. Оценка использует парные behavioral_signatures (clean / poisoned / ambiguous / unclear). Конструкция отравления остаётся неизменной.
Происхождение и эталонные метки являются эталонной истиной бенчмарка для оценки. Защиты никогда не получают интерфейс атаки, имена условий, эталонные ответы, происхождение или идентификаторы в качестве признаков промпта.
Оба раннера используют общую валидацию случаев, консолидацию памяти, нижестоящее решение, оценку и агрегацию. Они различаются только стеком LLM / памяти.
python -m memform run-langchain \
--cases outputs/mcq_item_audit/accepted_cases.jsonl \
--output-dir results/langchain_mcq \
--phase all \
--interfaces P1 P2 P3 P4 P5 \
--model MODEL
python -m memform run-llamaindex \
--cases outputs/mcq_item_audit/accepted_cases.jsonl \
--output-dir results/llamaindex_mcq \
--phase learned \
--interfaces P1 P2 P3 P4 P5 \
--model MODEL
Те же команды принимают outputs/freeform_item_audit/accepted_cases.jsonl. Оценка свободной формы использует точное каноническое совпадение, затем опциональные модели-парсеры / судьи (--freeform-parser-model, --freeform-judge-model).
| Флаг | Значение |
|---|---|
--phase oracle|learned|all | Oracle использует эталонный текст политики; learned консолидирует из скомпилированной истории |
--target-alignment | Условная по задаче оценка того, что рекомендует выученная память (диагностика) |
--p5-updaters | incremental_merge (по умолчанию), full_rewrite, recency_weighted_strict, batch_replay |
--p5-random-orders N | Дополнительные детерминированные перестановки P5 |
--cache | Дисковый кэш JSONL вызовов LLM |
--validate-only | Вывести план запуска и оценку количества вызовов, затем выйти |
Каждый запуск записывает case_results.jsonl и summary.json в --output-dir.