feat: add Weibull decay and rerank pipeline for search results#1032
Open
zackchiutw wants to merge 1 commit intoMemPalace:developfrom
Open
feat: add Weibull decay and rerank pipeline for search results#1032zackchiutw wants to merge 1 commit intoMemPalace:developfrom
zackchiutw wants to merge 1 commit intoMemPalace:developfrom
Conversation
Introduce a config-driven post-retrieval rerank pipeline that adjusts search ranking beyond raw cosine distance. Four stages are supported: Weibull time-decay, keyword overlap boost, emotional_weight boost, and optional LLM reranking via Anthropic API. All stages are independently toggleable via ~/.mempalace/config.json and backward-compatible — no config means identical behavior to before. The pipeline runs after upstream's closet boost + BM25 hybrid rank so those signals are preserved. When any stage is enabled, search_memories over-fetches 3x candidates so the reorder has headroom, applies the max_distance filter on the post-rerank fused_distance, and returns a reranked=True flag for transparency. Layer1 now supports optional read-time decay (k=1.2, λ=365, floor=0.6) and Layer3 is refactored to use the unified search_memories() output. Knowledge graph query_entity() accepts apply_decay to apply the same Weibull curve to stored confidence values at read time. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
4520e22 to
b3b9881
Compare
7 tasks
jphein
added a commit
to jphein/mempalace
that referenced
this pull request
Apr 19, 2026
Scanned all 233 open upstream PRs today against our open PRs and fork-ahead / planned-work items. Findings merged into README: - P2 (decay) and P3 Tier-0 (LLM rerank): both covered by MemPalace#1032 (@zackchiutw, MERGEABLE, 2026-04-19 — Weibull decay + 4-stage rerank pipeline). Older simpler version at MemPalace#337. Dropped as fork work; watching MemPalace#1032. - P7 (alternative storage): formally out of scope. RFC 001 MemPalace#743 (@igorls) defines the plugin contract; four backend PRs already in flight (MemPalace#700, MemPalace#381 Qdrant; MemPalace#574, MemPalace#575 LanceDB). Fork consumes, does not rebuild. - P0 (multi-label tags): still fork/upstream candidate. MemPalace#1033 (@zackchiutw) ships adjacent privacy-tag + progressive disclosure but not the full multi-label scheme. - Merged MemPalace#1023 section acknowledges complementary MemPalace#976 (felipetruman) which adds broader mine_global_lock() + HNSW num_threads pin. Gives future-us a map so we don't re-file MemPalace#1036-style duplicates.
jphein
added a commit
to jphein/mempalace
that referenced
this pull request
Apr 19, 2026
Changes (all 7 approved items): 1. Tighten line-15 status line to keep only non-redundant bits (test count, Discussion MemPalace#1017, issues link) 2. Remove "Fork Changes / Headlines" subsection — duplicated the three differentiators already in the lead paragraph 3. Remove "Planned work / Done" — 5 bullets of PR status already in the "Open upstream PRs" table 4. Trim P2 "original design notes" — MemPalace#1032 is MERGEABLE; kept the prune CLI fork-opportunity note 5. Tighten MemPalace#1023 row in "Merged upstream" — moved the MemPalace#976 mapping detail to a single compact sentence 6. Collapse "Pulled in from upstream v3.3.1" from 6 bullets to one paragraph pointing at the release notes 7. Prune three oldest "Superseded by upstream" bullets (epsilon mtime, .jsonl, max_distance — all upstream-authored or shipped by upstream before the fork claimed them as contributions) 8. Drop P7 "Original fork-mode design notes" (flashcard/AAAK/ diary modes) now that the section explicitly marks P7 as dropped fork work Net: 345 → 316 lines. No unique info removed; anything cut is either duplicated elsewhere in the same README or retrievable from the cited PR/release link.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces a config-driven post-retrieval rerank pipeline that adjusts search ranking beyond raw cosine distance. Four stages, independently toggleable via
~/.mempalace/config.json:emotional_weightmetadata get a small boostAll stages are off by default. No config = identical behavior to before. When any stage is enabled,
search_memoriesover-fetches 3× candidates, runs the pipeline after the existing closet-boost + BM25 hybrid rank (both preserved), re-appliesmax_distanceagainst the post-rerankfused_distance, and flags the response withreranked: Truefor transparency.Why
Raw cosine distance treats every memory as if it were written yesterday. For a memory system where identity and recency matter, that's a regression trap — old notes crowd out fresh ones. The pipeline is modular so users can tune the trade-off per palace (e.g., λ=90 days for a work palace, λ=365 for a personal history wing).
What changes
mempalace/reranker.py(new)fused_distancefieldmempalace/searcher.pyrerank=Trueparam onsearch_memories; pipeline runs after_hybrid_rankso closet/BM25 signals are preserved;_load_rerank_config+_apply_rerankhelpers keep complexity under the C901 thresholdmempalace/config.pyrerank_configproperty readingconfig.json["rerank"]mempalace/mcp_server.pyrerankparam + schema entry onmempalace_searchmempalace/layers.pysearch_memories()dictmempalace/knowledge_graph.pyquery_entity(apply_decay=...)applies the same Weibull curve to stored confidence at read timetests/test_reranker.py(new)tests/test_layers.pyExample config
{ "rerank": { "weibull_decay": {"enabled": true, "k": 1.5, "lambda": 90, "floor": 0.3}, "keyword_boost": {"enabled": true, "weight": 0.30}, "importance_boost":{"enabled": false, "weight": 0.15}, "llm_rerank": {"enabled": false, "model": "claude-haiku-4-5-20251001", "top_k": 10} } }Test plan
pytest tests/test_reranker.py tests/test_searcher.py tests/test_layers.py tests/test_config.py tests/test_mcp_server.py— 186 passedruff check .— all checks passedruff format --checkon modified files — cleanrerankkey in config,search_memoriesreturns identical output (norerankedflag, no new fields in response)mempalace_searchMCP tool acceptsrerank: falseto bypass the pipeline when desiredNotes for reviewers
rerankis enabled but no stages are configured, the pipeline is an identity function and thererankedflag stays falsellm_rerankstage is gated behind a local import ofanthropicand skipped if unavailable🤖 Generated with Claude Code