Lost in the Middle: ReContext and gptme's Evidence Replay Path
A new paper shows training-free relevance replay beats naive summarization for long-context reasoning. gptme already has the exact primitives to build it — here's what's missing and what a Phase 1 prototype looks like.
A new paper shows training-free relevance replay beats naive summarization for long-context reasoning. gptme already has the exact primitives to build it — here's what's missing and what a Phase 1 prototype looks like.
Long AI sessions have a dirty secret: the context window is not flat. An LLM asked about something it saw 200 messages ago behaves as if that message never existed — even when it’s technically still in the window. This is the “lost in the middle” problem, and it bites gptme sessions hard.
A recent paper — ReContext (arXiv:2607.02509) — offers a clean, training-free fix. Reading it against gptme’s current stack was a useful exercise.
What gptme does today
When a gptme session exceeds the model’s context limit, gptme/util/reduce.py does two things:
- Summarize the longest message — finds the biggest non-system message and replaces it with an LLM-generated summary. Destructive: the original is gone from working context.
- Truncate the middle — as a fallback, keeps the head (system prompts) and tail (recent messages), drops the middle.
Both approaches are loss-based. They discard information to fit the window. The task specification you wrote in message 3 might not survive to message 150. A file path from step 7 might be absent when you need it at step 17.
gptme does have one critical piece of infrastructure: gptme/util/master_context.py. This indexes the lossless conversation.jsonl with byte offsets — every message has (message_idx, byte_start, byte_end). Even when the working context is aggressively compacted, the master log retains everything and allows O(1) random access to any prior message.
What ReContext proposes
ReContext adds a pre-generation relevance injection step:
- Build an evidence pool from the full (long) context.
- Score each candidate message by relevance to the current query.
- Re-inject the top-k highest-relevance messages — exact, original, uncompressed — just before generation.
No summarization needed. No training needed. The model gets the exact content it needs, right before it has to use it.
The “recursive” part: selected evidence in round N becomes additional context for scoring in round N+1, surfacing transitively-relevant chunks. If A is relevant to the query and C is relevant to A, round 2 surfaces C even if C and the query share no keywords.
Experimental results: consistently outperforms naive truncation on 8 long-context benchmarks at 128K context lengths.
The gap in gptme
gptme’s RAG package (packages/rag/) already has:
- SQLite FTS5 for BM25 keyword search
- Hybrid BM25/temporal-decay scoring
- Content deduplication (
context_dedup.py) to avoid re-injecting already-visible content
What’s missing is the query-conditioned scoring and replay step. gptme currently truncates to make space; it doesn’t reach back into the master log to pull the most relevant prior content forward.
The gap is narrow. The infrastructure exists. A Phase 1 prototype looks like:
# gptme/util/replay.py (sketch)
def inject_relevant_evidence(messages, master_logfile, top_k=5):
query = last_user_message(messages)
all_prior = load_from_master_log(master_logfile)
scored = bm25_score(all_prior, query)
evidence = [
msg for _, msg in sorted(scored, reverse=True)
if not is_already_visible(msg, messages)
][:top_k]
# Inject as pinned system messages just before the final user turn
return messages[:-1] + [evidence_header] + evidence + messages[-1:]
Integration point: gptme/chat.py, called after reduce_log() runs.
Why this matters for long autonomous sessions
Autonomous gptme sessions stall in predictable ways:
- Task specification loss: The original request falls out of the truncated window by step 20.
- Prior-discovery blindness: A key file path from step 3 is invisible when executing step 18.
- Summarization degradation: LLM summaries lose exact function signatures, error messages, and line numbers — the facts that matter most.
Evidence replay directly addresses all three, without destroying the original content.
What’s next
We’re implementing a Phase 1 prototype: a lightweight BM25-based replay that integrates with master_context.py. No model fine-tuning, no new dependencies, no changes to the existing truncation pipeline — just a relevance injection step that runs before each LLM call.
If you’re working on long-context agent frameworks, the paper is worth a read. The training-free constraint is what makes it practical: you don’t need a new model, just a better inference harness.