This page reports the numbers of hotmemory on LongMemEval-S, a public benchmark of 500
questions over long chat histories. Each number on this page was observed on 2026-10-10,
except where a section gives another date. Each section names the result file that a run wrote into bench/results/, with its
numbers, its configuration, and the commit of hotmemory that ran it. Git ignores that
folder, so this page is the record of the numbers. bench/README.md
gives the commands that repeat each run and write the files again.
| Item | Value |
|---|---|
| Data file | longmemeval_s_cleaned.json, the cleaned release of 2025-09, revision 98d7416c of the dataset on Hugging Face |
| SHA-256 of the data file | d6f21ea9d60a0d56f34a05b609c79c88a451d2ae03597821ea3d5a9678c3a442 |
| Embedder | OpenAI text-embedding-3-small, 1,536 dimensions. Each text is cut to 8,191 tokens. |
| Driver | HotdataStore, except in the driver check |
| Engine, local | The local stack of docs/local.md, RuntimeDB image sha256:48046ae3bf22, hotdata-framework 0.14.1 |
Each question has its own history of 38 to 62 sessions. The runner sorts the sessions of a
question by date, because 211 of the 500 histories are out of order in the file. Each
session date becomes observed_at in UTC.
The retrieval score needs no model except the embedder. For each question, the runner
stores one episode for each session, with the user turns of that session as its content.
Then it searches with the question for the 50 closest episodes, with
Filter(kind="episode"). It compares the ranked sessions with the evidence sessions.
The metrics and the scored questions are those of the reference code of LongMemEval. For
the reference code, an evidence session has answer in its id and the answer in one of
its user turns. The
score leaves out the 30 abstention questions and the 51 questions with no evidence in a
user turn, so 419 questions are scored.
recall_any@k: when one evidence session is in the first k, the value is 1.recall_all@k: when every evidence session is in the first k, the value is 1.ndcg_any@kis the normalized discounted cumulative gain of the first k.
Each value below is the mean over the 419 scored questions. The run used the local stack,
with one question at a time in the tables. File:
retrieval-hotdata-local-isolated-fused-vector.json.
| Ranking | Metric | k=1 | k=3 | k=5 | k=10 | k=30 | k=50 |
|---|---|---|---|---|---|---|---|
| fused | recall_any |
0.8807 | 0.9594 | 0.9690 | 0.9928 | 1.0000 | 1.0000 |
| fused | recall_all |
0.2458 | 0.8329 | 0.9045 | 0.9570 | 1.0000 | 1.0000 |
| fused | ndcg_any |
0.8807 | 0.9067 | 0.9181 | 0.9311 | 0.9367 | 0.9367 |
| vector | recall_any |
0.8783 | 0.9666 | 0.9833 | 1.0000 | 1.0000 | 1.0000 |
| vector | recall_all |
0.2530 | 0.8592 | 0.9475 | 0.9928 | 0.9976 | 1.0000 |
| vector | ndcg_any |
0.8783 | 0.9247 | 0.9375 | 0.9479 | 0.9483 | 0.9485 |
ranking="fused" fuses BM25, the content vector, and the cue vector.
ranking="vector" ranks by the content vector alone. On this data, the vector ranking
scores higher than the fused ranking at k of 3 and more. The reason was not measured.
The same run, by question type:
| Question type | Questions | fused recall_all@5 |
vector recall_all@5 |
fused recall_all@10 |
vector recall_all@10 |
|---|---|---|---|---|---|
| single-session-user | 64 | 1.0000 | 0.9688 | 1.0000 | 1.0000 |
| single-session-assistant | 5 | 1.0000 | 1.0000 | 1.0000 | 1.0000 |
| single-session-preference | 30 | 0.8333 | 1.0000 | 0.9333 | 1.0000 |
| multi-session | 121 | 0.8430 | 0.9421 | 0.9256 | 0.9835 |
| knowledge-update | 72 | 1.0000 | 1.0000 | 1.0000 | 1.0000 |
| temporal-reasoning | 127 | 0.8740 | 0.8976 | 0.9449 | 0.9921 |
The LongMemEval paper reports retrieval only on its larger M split, so no published number on S compares with this table.
A second run kept the episodes of all 419 questions in the same tables, 19,864 rows, and
searched each question inside its own namespace. BM25 in the fused ranking takes its top
rows from the whole table before the namespace filter applies, so this run tests that
limit. On the local stack, the fused ranking scored higher at the top 5 and slightly lower
at the top 10. At the top 10, 1 more question had no evidence session. The vector ranking
gave the same sessions in the same order in both runs. File:
retrieval-hotdata-local-shared-fused-vector.json.
| Ranking | Tables hold | recall_any@5 |
recall_all@5 |
recall_any@10 |
recall_all@10 |
ndcg_any@10 |
|---|---|---|---|---|---|---|
| fused | one question | 0.9690 | 0.9045 | 0.9928 | 0.9570 | 0.9311 |
| vector | one question | 0.9833 | 0.9475 | 1.0000 | 0.9928 | 0.9479 |
| fused | every question | 0.9761 | 0.9165 | 0.9905 | 0.9499 | 0.9370 |
| vector | every question | 0.9833 | 0.9475 | 1.0000 | 0.9928 | 0.9479 |
On the first 20 scored questions, the vector ranking of MemoryStore and that of
HotdataStore gave the same sessions in the same order. The largest difference between
two distances was 1.0e-6. MemoryStore ran in process with a fixed clock. File:
retrieval-memory-in-process-isolated-vector-first20.json, compared with
bench/compare.py.
Each search time below includes the request to the engine and excludes the embedding of the question, which came from the cache. Each write stores the episodes of one question in one flush. Each delete removes them.
On the local stack, over the 419 questions of the retrieval run, with one question at a time:
| Operation | p50 | p95 | p99 | Highest |
|---|---|---|---|---|
| Search, fused | 130 ms | 205 ms | 273 ms | 517 ms |
| Search, vector | 42 ms | 65 ms | 95 ms | 138 ms |
| Write of one question | 0.29 s | 0.49 s | 0.62 s | 1.30 s |
| Delete of one question | 0.22 s | 0.38 s | 0.52 s | 1.05 s |
In the run with every question in one table, a write took 1.91 s at p50. Each flush reads the current rows of a table that grows.
On a cloud workspace, over the first 20 scored questions, with one question at a time.
File: retrieval-hotdata-cloud-isolated-fused-vector-first20.json.
| Operation | p50 | Highest |
|---|---|---|
| Search, fused | 998 ms | 1,675 ms |
| Search, vector | 361 ms | 1,068 ms |
| Write of one question | 2.77 s | 3.98 s |
| Delete of one question | 2.29 s | 2.94 s |
The cloud table gives no p95 or p99, because 19 searches after the first are too few for them. The first request of the cloud run took 17.7 s. The file does not prove that the engine was cold before it, so this page does not call it a cold start. The first search took 1,053 ms fused and 366 ms vector. The cloud run ranked the same sessions in the same order as the local run.
Three arms answer the same questions, with the same reader and the same judge. Each run uses one of two samples of 54 questions, 9 of each question type. A fixed seed chose each sample.
| Sample | File of ids | Seed | Abstention questions | Use |
|---|---|---|---|---|
| A | bench/sample.json | 20261010 |
2 | Each phase iterates on it. |
| B | bench/sample-b.json | 20261013 |
4 | Each phase runs it once, at its end. It holds no question of sample A. |
| Item | Value |
|---|---|
| Reader | gpt-4o-2024-08-06, temperature 0, up to 800 output tokens, the chain-of-thought prompt of the reference code |
| Judge | gpt-4o-2024-08-06, temperature 0, the prompt of the reference code for each question type |
| Extractor of the memory arm | gpt-4o-mini-2024-07-18, with the baseline prompt in bench/prompts.py, except in the section on extractor variants |
| Driver | HotdataStore with the fused ranking, on the local stack |
The arms:
- Full context: the reader gets every session of the question.
- Retrieval: the reader gets the 10 sessions that the fused search ranks first, with both roles.
- Memory:
captureruns on each session, in date order. Thenrecallgives the reader its block, with k of 30, a budget of 8,000 characters, andas_ofat 23:59:59 on the date of the question.
File: e2e-sample.json.
| Question type | Questions | Full context | Retrieval | Memory |
|---|---|---|---|---|
| single-session-user | 9 | 7 | 8 | 3 |
| single-session-assistant | 9 | 9 | 8 | 3 |
| single-session-preference | 9 | 8 | 8 | 3 |
| multi-session | 9 | 4 | 6 | 3 |
| knowledge-update | 9 | 5 | 7 | 4 |
| temporal-reasoning | 9 | 6 | 8 | 3 |
| All | 54 | 39 (72.2%) | 45 (83.3%) | 19 (35.2%) |
At the median, the reader read 113,689 tokens in the full-context arm, 29,878 in the retrieval arm, and 1,462 in the memory arm. The run made 2,802 model calls and cost $20.95.
On 2026-10-13, the memory arm ran again on sample A with --replay, from the cached
replies, at commit ce97385 with uncommitted changes to documentation only. It gave the same answer and the same mark on each of the 54
questions, with no model call and no embedder call. File: e2e-sample-a.json. On
2026-10-14, the same replay with --workers 4 at commit 4d99fbe gave the same 54 rows
again. It took 519 seconds, and the replay with one process took 2,264 seconds. File:
e2e-sample-a-workers4.json.
The LongMemEval paper reports 60.6% for full context with GPT-4o on all 500 questions of the earlier data file. A sample of 54 questions and the cleaned data file do not compare with that number closely.
Observed on 2026-10-14, at commit 5f2abb9. File: e2e-sample-b.json.
| Question type | Questions | Full context | Retrieval | Memory |
|---|---|---|---|---|
| single-session-user | 9 | 8 | 9 | 6 |
| single-session-assistant | 9 | 9 | 9 | 4 |
| single-session-preference | 9 | 3 | 6 | 0 |
| multi-session | 9 | 7 | 7 | 5 |
| knowledge-update | 9 | 8 | 8 | 5 |
| temporal-reasoning | 9 | 8 | 9 | 7 |
| All | 54 | 43 (79.6%) | 48 (88.9%) | 27 (50.0%) |
At the median, the reader read 113,314 tokens in the full-context arm, 30,899 in the retrieval arm, and 1,466 in the memory arm. The run made 2,869 model calls, cost $21.42, and took 2.9 hours with one process.
The memory arm scored 8 questions more on sample B than on sample A, with the same configuration. That is 14.8 points. A gain on one sample of 54 questions is therefore weak evidence, and a change counts only if both samples move the same way.
bench/diagnose.py ran capture again on each question that the memory arm missed, from
the cached extractor replies. GPT-4o then marked each stored fact that states the answer
or a value that the answer needs, and the search ranked every fact. A second GPT-4o call
then read the marked facts in the block. It told whether they hold every value that the
answer needs. Files: e2e-sample-a-diagnosis.json, observed on 2026-10-13,
and e2e-sample-b-diagnosis.json, observed on 2026-10-14.
| Cause | Sample A | Sample B |
|---|---|---|
| No stored fact states the answer or a value that it needs | 19 | 16 |
| A stored fact holds it, and the fused search ranked it below 30 | 2 | 0 |
A marked fact was in the top 30, and recall left it out |
0 | 0 |
| The block holds every needed fact, and the reader missed | 1 | 1 |
| The block holds some of the needed facts | 13 | 10 |
| Misses | 35 | 27 |
The three causes of phase 5 (19, 2, and 14 on sample A) are the same in this run, on each question. The split of the last group is new.
The extractor is the main loss on both samples. On sample A, phase 5 read the misses. Most often the extractor stored the interest of the user. It dropped what the assistant said, for example a number, a name, or an item of a list. In both questions of the second row, the vector ranking ranked the fact higher than the fused ranking did. When the block held a marked fact, it held every needed fact in only 2 of 25 misses. A question that needs several facts then lacks at least one of them.
The misses of each question type, on sample A:
| Question type | Misses | Not stored | Ranked below 30 | All present | Some present |
|---|---|---|---|---|---|
| single-session-user | 6 | 4 | 1 | 1 | 0 |
| single-session-assistant | 6 | 5 | 0 | 0 | 1 |
| single-session-preference | 6 | 4 | 1 | 0 | 1 |
| multi-session | 6 | 3 | 0 | 0 | 3 |
| knowledge-update | 5 | 2 | 0 | 0 | 3 |
| temporal-reasoning | 6 | 1 | 0 | 0 | 5 |
The misses of each question type, on sample B:
| Question type | Misses | Not stored | Ranked below 30 | All present | Some present |
|---|---|---|---|---|---|
| single-session-user | 3 | 3 | 0 | 0 | 0 |
| single-session-assistant | 5 | 4 | 0 | 0 | 1 |
| single-session-preference | 9 | 6 | 0 | 0 | 3 |
| multi-session | 4 | 1 | 0 | 0 | 3 |
| knowledge-update | 4 | 1 | 0 | 1 | 2 |
| temporal-reasoning | 2 | 1 | 0 | 0 | 1 |
Phase 7 tried two extractor prompts, each with gpt-4o-mini-2024-07-18, on the memory arm
only. Both are in bench/prompts.py.
| Variant | What the prompt asks for |
|---|---|
baseline |
The prompt of phases 5 and 6. |
detail |
The baseline rules, with four more. Read every turn. Keep a fact that the user states in passing. Keep each item of a list as its own fact. Write each date as an absolute date. |
From phase 7, each fact carries the source session:<hash>, with the first 12 hex digits
of the SHA-256 of the session id. The block shows the sources to the reader, so each line
is longer than in phases 5 and 6. The runs of phases 5 and 6 had no sources. The baseline
therefore ran again with sources, as the point of comparison. On 2026-10-14, at commit
db2fe63, a replay of sample A with --no-fact-sources gave the same answer and the same
mark on each of the 54 questions as phase 6, with no model call. File:
e2e-sample-a-replay-no-sources.json.
Observed on 2026-10-14, at commit a9d87c0, with 4 workers.
| Run | Sample | Correct of 54 | Facts per session | Reader tokens at the median | Sessions at the token limit | Cost | File |
|---|---|---|---|---|---|---|---|
baseline, no sources (phase 6) |
A | 19 | 5.34 | 1,462 | not recorded | see above | e2e-sample-a.json |
baseline |
A | 22 | 5.36 | 1,698 | 0 | at least $0.92 | e2e-sample-a-baseline-sources.json |
detail |
A | 31 | 5.39 | 1,655 | 1 | at least $1.73 | e2e-sample-a-detail.json |
baseline, no sources (phase 6) |
B | 27 | 5.20 | 1,466 | not recorded | see above | e2e-sample-b.json |
detail |
B | 32 | 5.00 | 1,664 | 0 | $1.71 | e2e-sample-b-detail.json |
The first try of each run on sample A stopped at question a3332713. One extractor reply
reached the limit of 4,000 output tokens on a session where the user pastes a list of
survey answers. From commit a9d87c0, such a reply gives no facts for its session, and
the run goes on. The second try took the replies of the first from the cache. The cost of
each run on sample A is the sum of both tries. The first try printed its cost only after
each question, so its last calls are not in the sum.
Correct answers by question type:
| Question type | baseline, A |
detail, A |
baseline no sources, B |
detail, B |
|---|---|---|---|---|
| single-session-user | 4 | 4 | 6 | 6 |
| single-session-assistant | 3 | 2 | 4 | 4 |
| single-session-preference | 3 | 4 | 0 | 1 |
| multi-session | 3 | 6 | 5 | 6 |
| knowledge-update | 4 | 8 | 5 | 7 |
| temporal-reasoning | 5 | 7 | 7 | 8 |
| All | 22 | 31 | 27 | 32 |
The diagnosis of each run, with the same commands as above. The diagnoses cost $0.31, $0.29, and $0.27.
| Cause | baseline, A |
detail, A |
baseline no sources, B |
detail, B |
|---|---|---|---|---|
| No stored fact states the answer or a value that it needs | 19 | 16 | 16 | 14 |
| A stored fact holds it, and the fused search ranked it below 30 | 1 | 1 | 0 | 0 |
A marked fact was in the top 30, and recall left it out |
0 | 0 | 0 | 0 |
| The block holds every needed fact, and the reader missed | 0 | 0 | 1 | 1 |
| The block holds some of the needed facts | 12 | 6 | 10 | 7 |
| Misses | 32 | 23 | 27 | 22 |
detail gained 13 questions on sample A over the baseline with sources, and lost 4. Of
the 13, 9 were misses where the block of the baseline held some of the needed facts. So
most of the gain comes from facts that are more complete, with exact values and absolute
dates. The group with no stored fact got smaller by 3 on sample A and by 2 on sample B.
Phase 7 read the misses and found these facts:
- Phase 5 said that the extractor dropped what the assistant said. On sample A, that holds for 5 of the 19 misses with no stored fact. The other 14 are a fact that the user states in passing, in a turn about another topic.
- With
detail, the extractor still drops what the assistant said. On sample A, 7 misses of the type single-session-assistant have no stored fact. For 3 of their sessions,detailwrote no fact at all. - The marker of the diagnosis can miss facts. On sample A,
detailstored the facts that hold the answer for2ce6a0f2,92a0aa75, and71017277, and the marker marked none of them. The marker reads all facts of a question in one call, 226 to 300 facts here. So the group with no stored fact can be smaller than the table shows, in each run.
Phase 8 stored each session as an episode beside its facts, and let recall add episodes
to the block after the facts. The runs use the detail extractor of phase 7, and the
options --session-episodes and --episodes of the runner. capture stores each session
under the key session-<hash>, with the hash of phase 7, and each fact cites that episode.
The block shows the source as session-<hash>@1. The facts carry no session:<hash>
source. The two values of episodes:
| Value | The episodes after the facts |
|---|---|
none |
No episode. The block holds the facts only. |
cited |
The episodes that the facts of the block cite, in the order of the facts. |
search |
The top 30 episodes of a fused search with the question. |
Each block holds whole episodes only, and it stops before the first episode that does not
fit in the budget. none was run at 16,000 characters only. With k of 30, its largest
block held 5,344 characters on sample A and 5,626 on sample B, so a larger budget gives
the same block.
Observed on 2026-10-15, at commit 320e891, with 4 workers.
| Run | Sample | Correct of 54 | Reader tokens at the median | Episodes in the block at the median | Gained and lost against none |
Cost | File |
|---|---|---|---|---|---|---|---|
none, 16,000 |
A | 29 | 1,715 | 0 | $0.52 | e2e-sample-a-p8-none-16k.json |
|
cited, 16,000 |
A | 31 | 1,728 | 0 | +3, -1 | $0.12 | e2e-sample-a-p8-cited-16k.json |
search, 16,000 |
A | 34 | 1,738 | 0 | +6, -1 | $0.08 | e2e-sample-a-p8-search-16k.json |
cited, 32,000 |
A | 38 | 6,300 | 2 | +10, -1 | $1.04 | e2e-sample-a-p8-cited-32k.json |
search, 32,000 |
A | 43 | 5,715 | 2 | +14, -0 | $0.75 | e2e-sample-a-p8-search-32k.json |
cited, 64,000 |
A | 44 | 12,446 | 4 | +15, -0 | at least $1.01 | e2e-sample-a-p8-cited-64k.json |
search, 64,000 |
A | 45 | 12,849 | 4 | +17, -1 | $1.93 | e2e-sample-a-p8-search-64k.json |
none, 16,000 |
B | 31 | 1,723 | 0 | $0.57 | e2e-sample-b-p8-none-16k.json |
|
search, 64,000 |
B | 45 | 12,676 | 4 | +15, -1 | $1.91 | e2e-sample-b-p8-search-64k.json |
The retrieval arm read 29,878 tokens at the median on sample A, and scored 45. search at
64,000 characters scored 45 on sample A and 45 on sample B, with 12,849 and 12,676 reader
tokens. Sample A and sample B moved the same way, from 29 to 45 and from 31 to 45.
The none runs scored 29 on sample A and 31 on sample B, against 31 and 32 with the
session:<hash> source of phase 7. The new source changes the line length in the block,
so the list of known facts that capture gives the extractor can change. Then the
extractor gets a new prompt and a new reply. The none runs are the baseline of this
section.
Each run after the first on a sample replayed capture from the extractor cache. A run
that changed only episodes or the budget paid for the reader and the judge only. The
first try of the runs with cited at 64,000 and every search run stopped at an internet
outage, and the next try of cited at 64,000 stopped at one engine error. Each later try
took the replies of the earlier tries from the cache. The log of the first try of cited at
64,000 was lost, so its cost is not known. The cost of a run is the sum of its tries. The
runs and the diagnoses cost at least $8.10.
Correct answers by question type:
| Question type | A none |
A cited 64,000 |
A search 32,000 |
A search 64,000 |
B none |
B search 64,000 |
|---|---|---|---|---|---|---|
| single-session-user | 3 | 9 | 9 | 8 | 6 | 9 |
| single-session-assistant | 2 | 6 | 9 | 9 | 2 | 9 |
| single-session-preference | 4 | 7 | 5 | 6 | 1 | 5 |
| multi-session | 6 | 6 | 6 | 6 | 6 | 7 |
| knowledge-update | 8 | 8 | 8 | 8 | 7 | 7 |
| temporal-reasoning | 6 | 8 | 6 | 8 | 9 | 8 |
| All | 29 | 44 | 43 | 45 | 31 | 45 |
The diagnosis of the none runs and of search at 64,000, with the commands above. The
last row counts the misses whose block held an evidence session as an episode. The
diagnoses cost $0.17 in total.
| Cause | A none |
A search 64,000 |
B none |
B search 64,000 |
|---|---|---|---|---|
| No stored fact states the answer or a value that it needs | 17 | 5 | 17 | 5 |
| A stored fact holds it, and the fused search ranked it below 30 | 1 | 0 | 0 | 0 |
A marked fact was in the top 30, and recall left it out |
0 | 0 | 0 | 0 |
| The block holds every needed fact, and the reader missed | 1 | 2 | 0 | 1 |
| The block holds some of the needed facts | 6 | 2 | 6 | 3 |
| Misses | 25 | 9 | 23 | 9 |
| The block held an evidence session as an episode | not run | 8 | not run | 8 |
The two target groups of the phase got smaller on both samples. The misses with no stored
fact went from 17 to 5 on each sample. The misses with some needed facts went from 6 to 2
on sample A and from 6 to 3 on sample B. The none runs missed every question of the
type single-session-assistant with no stored fact, 7 on each sample. search at 64,000
missed none of that type. In 8 of the 9 misses on each sample, the block held an evidence
session. A question of the type multi-session can need more sessions than the block held.
The type single-session-preference has the most misses with search at 64,000: 3 on
sample A and 4 on sample B.
Phase 9 kept the memory of a run and reused it for runs that change only recall. The
section "Faster runs" of bench/README.md gives the options. Each run
below is --replay on sample A, with --extractor detail --session-episodes and 4
workers, so no run called a model. Observed on 2026-10-16, at commit 630e3be. The last commit that
changed src/hotmemory is b5443ac, the same code as the phase 8 runs.
| Run | Correct of 54 | Time | Rows equal to | File |
|---|---|---|---|---|
search, 64,000, --keep |
45 | 762.4 s | phase 8 search 64,000: 54 of 54 |
e2e-sample-a-p9-keep-search-64k.json |
search, 32,000, --reuse |
43 | 13.0 s | phase 8 search 32,000: 54 of 54 |
e2e-sample-a-p9-reuse-search-32k.json |
cited, 64,000, --reuse |
44 | 15.3 s | phase 8 cited 64,000: 54 of 54 |
e2e-sample-a-p9-reuse-cited-64k.json |
search, 64,000, --reuse |
45 | 11.1 s | the --keep run: 54 of 54, with the same block SHA-256 |
e2e-sample-a-p9-reuse-search-64k.json |
Two rows are equal in four values: the answer, the verdict, the block length, and the
episodes in the block. The --keep run also wrote the same count of facts for each question as
phase 8. The phase 8 runs of the same configurations took 1,133 to 2,085 seconds, and
those times include model calls that were not in the cache. The 54 kept databases hold
192 MB in the storage of the local engine.
The diagnosis of the --keep run read the kept databases, and did not run capture. It
took 7 seconds and called no model. For each of the 9 misses, it gave the same cause,
marked facts, and evidence check as the phase 8 diagnosis of search at 64,000.
The smoke run uses the same options with search at 64,000 characters, on the 18
questions of bench/sample-smoke.json and MemoryStore, in one process. Its first run
paid for the extraction. MemoryStore ranks by vector only, so the extractor saw other
lists of known facts than in the runs on the local engine. Observed on
2026-10-16, at commit 298fbe7:
| Run | Correct of 18 | Time | Cost | Model calls | File |
|---|---|---|---|---|---|
First, --run |
16 | 2,080.0 s | $1.07 | 842 | e2e-smoke-p9-first.json |
Again, --replay |
16 | 12.7 s | $0 | 0 | e2e-smoke-p9-cached.json |
Again, --replay --workers 4 |
16 | 3.8 s | $0 | 0 | e2e-smoke-p9-cached-w4.json |
Each replay gave the same answer, verdict, and block SHA-256 for each of the 18 questions.
With 4 workers, each worker holds a MemoryStore of its own. A first run with 4 workers
was not measured.
The time in the table is duration_s of the result file. The whole command took 563
seconds the first time, and 14.9 seconds on a later try. The cause of the first wait was
not found.
- The end-to-end numbers come from samples of 54 questions, so one question moves an arm by 1.9 points. The memory arm differs by 14.8 points between sample A and sample B. A run on all 500 questions waits for the owner's agreement.
- The full-context arm gives the reader every session. The reference code keeps the last 50 sessions, so the two differ for histories longer than 50 sessions.
- The memory arm tried one extractor model,
gpt-4o-mini-2024-07-18, with two prompts. A stronger extractor model was not measured. - The diagnosis marks the facts of a question in one model call, and it can miss facts in a long list. Its count of misses with no stored fact can be too high.
- The reader prompt of the memory arm calls the block "facts extracted from history chats", also when the block holds episodes. A prompt that names the episodes was not tried.
- In the runs of phase 8, the local engine refused one fused search once, because it
found a BM25 index of
memory_v1stale against its table. A second try of the same run did not show the error. The cause was not found. recallkeeps the records that are valid atas_of, and a search over history does not exist yet. A question about a value before it changed can need a superseded record.