
Deterministische Benchmark- und Evaluierungsumgebung für Persistent-Memory-Poisoning in LLM-Agenten, mit paarweisen sauberen/vergifteten Fällen, LangChain/LlamaIndex-Runnern und Abwehrmechanismen.
Dieses Repository begleitet das Paper MemForm: Benchmarking Memory Formation Poisoning in LLM Agents.
MemForm ist ein deterministischer Benchmark für die Vergiftung persistenten Gedächtnisses in LLM-Agenten. Er stellt eine kausale Frage, die gewöhnliche Jailbreak- oder Prompt-Injection-Suiten nicht isolieren:
Wenn das Langzeitgedächtnis eines Agenten an einer wohldefinierten Schnittstelle verändert wird, verschiebt sich dann die nachgelagerte Entscheidungsfindung bei derselben Aufgabe von einer sauberen Policy zu einer vergifteten Policy?
Jedes Element ist eine gepaarte Intervention. Der nachgelagerte Auslöser, der Aktionsraum und die Familiensemantik bleiben fest. Nur die gedächtnisbildende Eingabe ändert sich zwischen der sauberen und der vergifteten Bedingung. Angriffserfolg ist ein Kontrast innerhalb eines Elements.
Dieses Release enthält die eingefrorenen Benchmark-Fälle und die Evaluierungs-/Verteidigungs-Runner. Die Konstruktionspipeline wird zurückgehalten, solange das Paper begutachtet wird, und wird nach der Veröffentlichung freigegeben.
Jede Familie wird an fünf Gedächtnis-Schnittstellen instanziiert. Das Fallfeld ist interface. P1–P5 sind die Namen aus dem Paper: Content, Evidence, Scope, Selection und Path.
| Schnittstelle | Paper-Name | Kausale Variable | Kontrast sauber vs. vergiftet | Nachgelagerte Probe |
|---|---|---|---|---|
| P1 | Content | Gespeicherter Gedächtnistext | Direktes Schreiben einer sauberen wiederverwendbaren Policy vs. einer vergifteten Policy | Eine allgemeine Zielaufgabe |
| P2 | Evidence | Authentizität der Stützbelege | Authentische Historie mit gleichem Budget vs. eine abgestimmte Historie, die einige Belege durch gefälschte Belege ersetzt. Die Provenienz ist vor dem Gedächtnislerner verborgen | Eine allgemeine Zielaufgabe |
| P3 | Scope | Beobachtete Scope-Verteilung | Lokal gültige Belege plus externe Gegenbeispiele vs. cue-saliente interne Erfolge plus authentische externe/allgemeine Erfolge für die lokal bevorzugte Aktion | Drei Aufgaben: im Scope, nahe außerhalb des Scopes, Ziel außerhalb des Scopes |
| P4 | Selection | Beibehaltene Teilmenge | Derselbe Kandidatenpool; saubere vs. vergiftete Beibehaltung einer Teilmenge fester Größe, mit einer Vollpool-Kontrolle | Eine allgemeine Zielaufgabe |
| P5 | Path | Nur die Konsolidierungsreihenfolge | Dieselbe Multimenge kontextgleicher Erfahrungen in zwei Permutationen. Sauberer Beleg steht in der sauberen Reihenfolge zuletzt; vergifteter Beleg steht in der vergifteten Reihenfolge zuletzt | Eine kontextgleiche Zielaufgabe |
P3 im Scope ist eine Übereinstimmungs-/Shared-Target-Kontrolle: saubere und vergiftete Gold-Antworten sind identisch. Nahe-außerhalb- und Ziel-außerhalb-Aufgaben sind die trennbaren Proben. P5 verbietet versteckte Kontextverschiebungen: Jeder Datensatz teilt einen context_key, und sowohl saubere als auch vergiftungsstützende Datensätze sind beobachtete Erfolge.
| Pfad | Inhalt |
|---|---|
outputs/mcq_item_audit/accepted_cases.jsonl | Eingefrorene Multiple-Choice-Fälle (994 Elemente, 235 Familien) |
outputs/freeform_item_audit/accepted_cases.jsonl | Eingefrorene Freiform-Fälle (897 Elemente, 218 Familien) |
memform/eval/ | Gemeinsames Protokoll plus LangChain-/LlamaIndex-/Verteidigungs-Runner |
memform/freeform/evaluator.py | Kaskadierter Adjudikator für Freiform-Antworten |
memform/defenses/ | Schreibzeit-Verteidigungen, Nutzungszeit-Task-Shield und Metriken mit festem Nenner |
memform/common.py | JSONL-I/O und Prüfungen des Fallschemas |
Anzahlen nach Schnittstelle — MCQ: P1 234, P2 233, P3 174, P4 144, P5 209. Freiform: 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
Root-run_*.py-Skripte rufen dieselben Einstiegspunkte auf wie python -m memform <command>.
Python 3.10+.
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
Kopiere .env.example nach .env und setze die Zugangsdaten:
| Variable | Verwendet von |
|---|---|
OPENAI_API_KEY | Evaluierungs-Agent / Speichermodell |
OPENAI_BASE_URL | Optionales OpenAI-kompatibles Gateway (OPENAI_API_BASE wird auch von LlamaIndex akzeptiert) |
JUDGE_OPENAI_API_KEY / JUDGE_OPENAI_BASE_URL | Optionaler separater Judge / Freiform-Evaluator |
DEFENSE_OPENAI_API_KEY / DEFENSE_OPENAI_BASE_URL | Optionaler separater Endpunkt für das Verteidigungsmodell |
--api-key und --base-url überschreiben die Umgebungsvariablen. Jeder OpenAI-kompatible Chat-Completions-Server funktioniert. Die Standardmodellnamen der CLI sind Platzhalter; übergib ein Modell, das auf deinem Endpunkt verfügbar ist.
python -m memform --help
JSONL, ein Fall pro Zeile.
Gemeinsame Felder: case_id, family_id, interface (P1–P5), attack_type, domain, decision_variable, clean_policy, poisoned_policy, scope, candidate_experiences, memory_building, metadata.
memory_building ist die gepaarte Intervention:
oracle_memory.clean / oracle_memory.poisoned — Gold-Policy-Text (diagnostisch)clean_condition / poisoned_condition — Memory-Building-Eingabe für diese SchnittstelleMCQ. evaluation.type ist multiple_choice. Jeder trigger_tasks[]-Eintrag hat task, choices, clean_answer und poisoned_answer.
Freiform. task_format ist free_form; source_case_id verweist auf die MCQ-Quelle. Optionsmenüs werden durch eine offene Empfehlung ersetzt. Die Bewertung verwendet gepaarte behavioral_signatures (clean / poisoned / ambiguous / unclear). Die Konstruktion der Poisoning bleibt unverändert.
Provenienz und Gold-Labels sind Benchmark-Ground-Truth für die Bewertung. Defenses erhalten niemals die Angriffsschnittstelle, Bedingungsnamen, Gold-Antworten, Provenienz oder IDs als Prompt-Features.
Beide Runner teilen sich Fallvalidierung, Memory-Konsolidierung, Downstream-Entscheidung, Bewertung und Aggregation. Sie unterscheiden sich nur im LLM-/Memory-Stack.
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
Dieselben Befehle akzeptieren outputs/freeform_item_audit/accepted_cases.jsonl. Die Freiform-Bewertung verwendet exakte kanonische Übereinstimmung, dann optionale Parser-/Judge-Modelle (--freeform-parser-model, --freeform-judge-model).
| Flag | Bedeutung |
|---|---|
--phase oracle|learned|all | Oracle verwendet Gold-Policy-Text; learned konsolidiert aus der kompilierten Historie |
--target-alignment | Aufgabenbedingter Judge darüber, was das gelernte Gedächtnis empfiehlt (diagnostisch) |
--p5-updaters | incremental_merge (Standard), full_rewrite, recency_weighted_strict, batch_replay |
--p5-random-orders N | Zusätzliche deterministische P5-Permutationen |
--cache | JSONL-Disk-Cache für LLM-Aufrufe |
--validate-only | Gibt den Ausführungsplan und die geschätzten Aufrufzahlen aus und beendet dann |
Jeder Lauf schreibt case_results.jsonl und summary.json unter --output-dir.