|
2 | 2 |
|
3 | 3 | MemTrace includes a deterministic benchmark that compares memory strategies across agent-memory failure modes. It is designed to prove that state-aware retrieval, admission gating, negative evidence, and compaction improve prompt context without relying on live LLM calls. |
4 | 4 |
|
| 5 | +Beyond the deterministic core, several **opt-in** benches validate the same claims on real data — real SWE-agent execution trajectories, live cross-model dogfooding, and the real LongMemEval / LoCoMo datasets with real embeddings and a real LLM judge (plus a head-to-head vs Mem0). Each skips cleanly without an endpoint and never affects the 16/16 acceptance. |
| 6 | + |
5 | 7 | ## Run the benchmark |
6 | 8 |
|
7 | 9 | ```bash |
@@ -97,7 +99,7 @@ benchmark / reproducibility impact). Against a local OpenAI-compatible proxy: |
97 | 99 | ```bash |
98 | 100 | MEMTRACE_LLM_API_KEY=sk-local \ |
99 | 101 | MEMTRACE_LLM_BASE_URL=http://localhost:4141/v1 \ |
100 | | -MEMTRACE_LLM_MODEL=gpt-5-mini \ |
| 102 | +MEMTRACE_LLM_MODEL=gpt-5.4 \ |
101 | 103 | uv run python -m app.benchmark.qa_bench --output-dir reports |
102 | 104 | ``` |
103 | 105 |
|
@@ -234,6 +236,102 @@ run). Retrieval also uses lexical/deterministic vectors here (no real embedding |
234 | 236 | endpoint), so absolute accuracy is modest. This proves the pipeline on real data |
235 | 237 | + a real model; it is not a leaderboard submission. |
236 | 238 |
|
| 239 | +## Real dataset at scale — LongMemEval + Mem0 head-to-head (opt-in) |
| 240 | + |
| 241 | +`app/benchmark/longmemeval_bench.py` runs the real |
| 242 | +[LongMemEval](https://github.com/xiaowu0162/LongMemEval) long-term-memory benchmark |
| 243 | +end-to-end with **real semantic embeddings** (OpenAI-compatible |
| 244 | +`text-embedding-3-small`, 256-dim cosine), a **real LLM** answering, and a **real |
| 245 | +LLM judge** grading against gold answers. Each question ships its own haystack of |
| 246 | +gold + distractor sessions; a 300-question run retrieves over **25,486 real memory |
| 247 | +records**. This is the current headline real-dataset check. |
| 248 | + |
| 249 | +```bash |
| 250 | +./scripts/fetch-longmemeval.sh s_cleaned # -> /tmp/longmemeval_s_cleaned.json (264MB; `oracle`=14MB smoke; `--clean` deletes) |
| 251 | +MEMTRACE_LLM_API_KEY=... MEMTRACE_LLM_BASE_URL=http://localhost:4141/v1 MEMTRACE_LLM_MODEL=gpt-5.4 \ |
| 252 | + MEMTRACE_RETRIEVAL_HYBRID_BACKEND=inmemory MEMTRACE_RETRIEVAL_GRAPH_BACKEND=inmemory \ |
| 253 | + uv run --with ijson python -m app.benchmark.longmemeval_bench --dataset /tmp/longmemeval_s_cleaned.json --limit 300 |
| 254 | +``` |
| 255 | + |
| 256 | +On a 300-question run (`gpt-5.4` judge): no-memory **0%** → plain vector **71.0%** → |
| 257 | +MemTrace **72.7%**, with MemTrace **≥ plain vector on every question type** (clearest |
| 258 | +lift on preferences, 63.3% → 70.0%). Memory is what turns 0% into ~73%; the |
| 259 | +state-aware gate then adds a small consistent edge. Kept light on purpose: |
| 260 | +embeddings come from the API, the 264MB file is stream-parsed (`--with ijson`), each |
| 261 | +question uses a fresh in-memory store (peak RSS ~100MB), and embeddings are cached |
| 262 | +between runs. Useful flags: `--max-sessions` (haystack depth), `--abstention-only` |
| 263 | +(the `_abs` questions — pair with `MEMTRACE_RETRIEVAL_MIN_RELEVANCE` to measure the |
| 264 | +relevance floor: **86.7%** correct abstention vs **83.3%** with **62% fewer** |
| 265 | +injected tokens), `--concurrency`, `--no-cache`. |
| 266 | + |
| 267 | +**Head-to-head vs Mem0.** `app/benchmark/mem0_compare.py` compares four conditions — |
| 268 | +no-memory, plain vector, [Mem0](https://github.com/mem0ai/mem0) (LLM fact-extraction |
| 269 | ++ semantic recall, configured *fairly* with per-fact timestamps), and MemTrace — over |
| 270 | +the **same** questions, embeddings, LLM answering, and one shared LLM judge. It is |
| 271 | +resumable via a checkpoint JSONL, so a killed run continues where it left off. |
| 272 | + |
| 273 | +```bash |
| 274 | +./scripts/fetch-longmemeval.sh s_cleaned |
| 275 | +MEMTRACE_LLM_API_KEY=... MEMTRACE_LLM_BASE_URL=http://localhost:4141/v1 MEMTRACE_LLM_MODEL=gpt-5.4 \ |
| 276 | + MEMTRACE_RETRIEVAL_HYBRID_BACKEND=inmemory \ |
| 277 | + uv run --with ijson --with mem0ai --with chromadb \ |
| 278 | + python -m app.benchmark.mem0_compare --dataset /tmp/longmemeval_s_cleaned.json --limit 30 |
| 279 | +``` |
| 280 | + |
| 281 | +On a 30-question sample: no-memory **0%**, Mem0 **56.7%**, plain vector **70.0%**, |
| 282 | +MemTrace **66.7%**. Both retrieval approaches beat Mem0, whose per-session LLM |
| 283 | +fact-extraction is **~30× slower to ingest** and lossy on detail-recall questions. |
| 284 | +(n=30 is small — plain vector edges MemTrace within noise here; the 300-question run |
| 285 | +above has MemTrace ≥ plain vector on every type. Mem0 runs on default Chroma + the |
| 286 | +local proxy, not its hosted Platform.) |
| 287 | + |
| 288 | +## Real agent trajectories + dogfooding (opt-in) |
| 289 | + |
| 290 | +The synthetic execution-tree bench above shows the mechanism in isolation; these two |
| 291 | +run it on **real** agent data — MemTrace's home turf. |
| 292 | + |
| 293 | +**Real SWE-agent trajectories.** `app/benchmark/agentic_trace_bench.py` ingests real |
| 294 | +[SWE-agent](https://github.com/SWE-agent/SWE-agent) (mini-swe-agent) execution |
| 295 | +trajectories — sequences of (assistant action, tool observation) turns that include |
| 296 | +genuinely failed shell commands (non-zero `<returncode>`) — into the real |
| 297 | +`MemoryRuntime` with failed steps finished `failed` and rolled back, then A/B |
| 298 | +compares retrieval over the identical memory (`baseline_1` plain vector vs |
| 299 | +`variant_2` MemTrace). Deterministic (no LLM); trajectories are streamed bounded from |
| 300 | +HuggingFace, so the full 66k-trajectory dataset is never downloaded. |
| 301 | + |
| 302 | +```bash |
| 303 | +./scripts/fetch-swe-trajectories.sh # stream MEMTRACE_SWE_N (default 250) trajectories -> /tmp/swe_trajs |
| 304 | +uv run python -m app.benchmark.agentic_trace_bench --dir /tmp/swe_trajs --output-dir reports |
| 305 | +``` |
| 306 | + |
| 307 | +Latest run — **3,048 trajectories / 81,758 real steps (5,061 failed)**: plain vector |
| 308 | +re-surfaces dead-branch commands the agent already abandoned (contamination |
| 309 | +**8.7%**), while MemTrace's gate isolates **all** of them (**0.0%**) at a ~1.6-pt |
| 310 | +recall cost (82.2% → 80.6%). `--limit` caps trajectories; `--top-k` / |
| 311 | +`--token-budget` tune retrieval. |
| 312 | + |
| 313 | +**Cross-model dogfooding A/B.** `app/benchmark/dogfood_agent.py` wires MemTrace into |
| 314 | +a real coding-agent loop (a real LLM proposes shell commands; a **sandboxed**, |
| 315 | +deny-listed executor runs them in a throwaway temp project) and measures whether |
| 316 | +memory stops the agent repeating a mistake. Phase 1 the agent learns a trap by |
| 317 | +hitting it (a required `./setup.sh` before `./check.sh`, discoverable only by |
| 318 | +running); phase 2 a fresh agent solves the same-shaped task **A = no memory** vs |
| 319 | +**B = MemTrace** — B surfaces both what worked and the failure-aware |
| 320 | +*avoided-attempts* negative channel. `--models` runs it across model families, |
| 321 | +`--trials` per model, `--concurrency` in parallel. |
| 322 | + |
| 323 | +```bash |
| 324 | +MEMTRACE_LLM_API_KEY=... MEMTRACE_LLM_BASE_URL=http://localhost:4141/v1 \ |
| 325 | + uv run python -m app.benchmark.dogfood_agent --models "gpt-5.4,claude-sonnet-5,gemini-3.1-pro-preview" --trials 100 |
| 326 | +``` |
| 327 | + |
| 328 | +Across 3 model families × ~100 trials (**298 total**): the agent repeated the |
| 329 | +mistake **298/298** with no memory → **88/298** with MemTrace (~34% fewer steps). |
| 330 | +Per model: gpt-5.4 100 → **0**, gemini-3.1-pro 98 → **0**, claude-sonnet-5 100 → 88. |
| 331 | +Honest read: the negative-memory channel eliminates the repeat for models that heed |
| 332 | +memory; claude-sonnet-5 tends to run the check first regardless, so the benefit |
| 333 | +depends on the model using the signal MemTrace supplies. |
| 334 | + |
237 | 335 | ## Performance / load testing (resource-capped) |
238 | 336 |
|
239 | 337 | `app/benchmark/perf_bench.py` measures wall-clock cost (the correctness benchmark |
|
0 commit comments