Running the benchmarks

September 8, 2026 · View on GitHub

One runner, four benchmarks, four stages: ADD, SEARCH, ANSWER, JUDGE. Per-benchmark rules live in benchmarks/adapters/<name>.py.

Also available in Chinese: README.zh.md.


1. Install dependencies

uv sync

2. Get the data

BenchmarkTarget pathSource
LoCoMobenchmarks/data/locomo10.jsonsnap-research/locomo
LongMemEvalbenchmarks/data/longmemeval_s.jsonxiaowu0162/longmemeval
EverMemBenchbenchmarks/data/evermembench.jsonEverMind-AI/EverMemBench-Dynamic
SubtleMemorybenchmarks/data/subtlememory/Yummytanmo/SubtleMemory

EverMemBench — download the snapshot to benchmarks/data/raw/EverMemBench-Dynamic/, then run python -m benchmarks.adapters.evermembench once.

SubtleMemory — keep the persona_0 .. persona_9 directory layout.

3. Configure the environment

cp benchmarks/.env.example benchmarks/.env
RoleKeysNotes
Extraction modelEVEROS_LLM__MODEL / __API_KEY / __BASE_URLused by ADD
Retrieval modelBENCH_DECIDER_MODEL / BENCH_DECIDER_BASE_URLthe multi-round decider; defaults to qwen3.6-27B, and falls back to the extraction model when no endpoint is set
Answer modelANSWER_API_KEY / ANSWER_BASE_URLmodel name in the config
Judge modelJUDGE_API_KEY / JUDGE_BASE_URLmodel name in the config

Models, top_k, retrieval settings and concurrency are set in benchmarks/configs/<dataset>.toml. reproduce.sh passes no model overrides.

4. Run

# all conversations, all four stages
DATASET=locomo bash benchmarks/reproduce.sh

# smoke test: one conversation, 10 sampled questions
DATASET=locomo CONV=0 bash benchmarks/reproduce.sh --smoke
VariableDefaultValues
DATASETlocomolocomo | longmemeval | subtlememory | evermembench
CONVallconversation indices
STAGESadd search answer judgeany subset, in order
RUNderivedresult directory name

reproduce.sh starts and stops its own EverOS servers.

StageAction
ADDstreams conversations into EverOS, which extracts memories
SEARCHone retrieval per question; records the injected episodes
ANSWERanswers each question from those episodes
JUDGEgrades each answer against the reference

Each stage appends per-conversation JSONL and skips entries already present, so an interrupted run resumes.

5. Output

benchmarks/results/<Dataset>/<run>/
├── report.txt            summary
├── report.json           machine-readable summary
├── run_spec.json         models served, endpoints, package versions, knobs
├── store/                built by ADD; absent when --everos-root points elsewhere
├── conv<N>/
│   ├── search_<method>.jsonl
│   ├── answer_<method>.jsonl
│   └── judge_<method>.jsonl
└── traces/               per-round retrieval traces

run_spec.json records the models actually served and the everalgo package versions, which determine what a store contains.

6. Results

Each benchmark's published number, produced by the configuration in benchmarks/configs/<dataset>.toml.

BenchmarkQuestionsAccuracyDeciderAnswer model
LoCoMo1,54094.42deepseek/deepseek-v4-flash-0731openai/gpt-4.1-mini
LongMemEval50094.00qwen3.6-27Bgoogle/gemini-3.6-flash
EverMemBench2,40066.67qwen3.6-27Bgoogle/gemini-3-flash-preview
SubtleMemory1,52271.75qwen3.6-27Bopenai/gpt-5.4

Accuracy is a micro accuracy for every benchmark in this table: sum(correct) / sum(total) over all graded questions. The per-category lines in report.txt are reported, never averaged into it, so a category with few questions moves the headline less than a large one does. This note used to say EverMemBench scored as the mean of its nine category columns — a macro average, which is a different statistic and not what run.py computes.

Two things follow, both worth knowing before comparing the number to anyone else's. Five of the six rows in the published EverMemBench comparison table are the macro mean of their own nine columns, so reading our figure alongside that column compares two different statistics. And the "nine categories" is not something this code can confirm: the adapter names three (F_SH, F_MH, F_TP in adapters/evermembench.py) and derives the rest from a question-id prefix, so any unlabelled id is reported under its raw key.

SubtleMemory — routes each question between two answer contracts on whether fact extraction found a conflict; the adapter does this automatically.


run.py flags

FlagMeaning
--convconversation indices, or all
--stagesany of add search answer judge
--everos-rootstore to use; default <results>/<run>/store
--serversEverOS servers to run in parallel
--results-rootoutput root; default benchmarks/results/<Dataset>
--data-pathdataset path for one run
--methodsllm_multiround | hybrid | agentic
--answer-model / --judge-modelmodel override for one run
--decider-model / --decider-base-urldecider; set both
--smoke10 sampled questions per conversation