Skip to content

fix(consolidation): reduce decay rate, add importance floor, filter archived memories (#78)#105

Merged
jack-arturo merged 3 commits intomainfrom
exp/78-decay-fix
Mar 2, 2026
Merged

fix(consolidation): reduce decay rate, add importance floor, filter archived memories (#78)#105
jack-arturo merged 3 commits intomainfrom
exp/78-decay-fix

Conversation

@jack-arturo
Copy link
Copy Markdown
Member

Summary

Fixes the overly aggressive memory decay formula that destroyed 84% of production memories within 30 days, regardless of importance.

The problem: base_decay_rate=0.1 (exponential) meant a 30-day memory had exp(-3) = 0.05 relevance, and a 90-day memory had exp(-9) = 0.0001. Production audit showed:

  • 84.3% of 9,318 memories classified as "archive" (relevance < 0.05)
  • 2,736 high-importance (≥0.7) memories with relevance < 0.1 ("unfairly killed")
  • 409 protected types (Decision/Insight) with near-zero relevance
  • Average relevance score: 0.049

The fix:

  • Decay rate: 0.1 → 0.01 (configurable via CONSOLIDATION_BASE_DECAY_RATE), changing the half-life from ~7 to ~69 days
  • Importance floor: relevance = max(calculated, importance * 0.3) — a memory with importance 0.8 can never decay below 0.24. Configurable via CONSOLIDATION_IMPORTANCE_FLOOR_FACTOR
  • Archive filter: Added coalesce(m.archived, false) = false to keyword search (was only filtered in trending). Added post-filter for Qdrant vector search. Consolidated archived flag syncs to Qdrant payload.
  • Rehabilitation scripts: scripts/audit_relevance.py (read-only damage assessment) and scripts/rescore_relevance.py (one-time recalculation with --dry-run and --target railway options)

Deployment safety: Delete/archive thresholds remain at 0.0 (disabled). After merge and deploy:

  1. Run rescore_relevance.py --target railway --dry-run to preview
  2. Run rescore_relevance.py --target railway to rehabilitate (avg score: 0.049 → 0.376)
  3. Monitor for 1 week, then enable conservative thresholds

Benchmark Results

Benchmark Baseline This PR Delta
locomo-mini (304 Qs) 76.97% 76.97% +0.0%
locomo-full (1986 Qs) 80.06% 79.51% -0.55% (within variance)

No regression — expected since benchmark snapshots use fresh data unaffected by production decay.

Test plan

  • Unit tests pass (make test — 110 passed, 11 skipped)
  • Consolidation engine tests updated for new formula
  • locomo-mini: 76.97% (no change)
  • locomo-full: 79.51% (-0.55%, within variance)
  • Rescore dry-run against production: avg 0.049 → 0.376, 9,257 improved
  • Production backup taken before any changes
  • Post-merge: run rescore on production
  • Post-rescore: monitor decay health for 1 week
  • After 1 week: enable thresholds (CONSOLIDATION_DELETE_THRESHOLD=0.01, CONSOLIDATION_ARCHIVE_THRESHOLD=0.05)

Closes #78

Made with Cursor

…rchived from all search paths (#78)

The original decay formula (base_decay_rate=0.1) destroyed 84% of memories
within 30 days regardless of importance. This commit:

- Reduces base_decay_rate from 0.1 to 0.01 (configurable via env var),
  changing the half-life from ~7 to ~69 days
- Adds importance-based floor: relevance = max(calculated, importance * 0.3),
  so a memory with importance 0.8 never decays below 0.24
- Filters archived memories from keyword search (was only filtered in trending)
- Filters archived memories from vector search (Qdrant post-filter + payload sync)
- Syncs archived flag to Qdrant payload when consolidation archives a memory
- Adds audit_relevance.py and rescore_relevance.py scripts for production
  data rehabilitation
- Keeps delete/archive thresholds at 0 (disabled) — will be enabled after
  production rescore

New env vars: CONSOLIDATION_BASE_DECAY_RATE, CONSOLIDATION_IMPORTANCE_FLOOR_FACTOR

Refs #78

Made-with: Cursor
locomo-mini: 76.97% (+0.0) — no regression on fresh data.
Full locomo pending.

Made-with: Cursor
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 2, 2026

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

📥 Commits

Reviewing files that changed from the base of the PR and between 14bed1e and 97e50f5.

📒 Files selected for processing (12)
  • CLAUDE.md
  • app.py
  • automem/config.py
  • automem/consolidation/runtime_bindings.py
  • automem/consolidation/runtime_helpers.py
  • automem/search/runtime_recall_helpers.py
  • benchmarks/EXPERIMENT_LOG.md
  • consolidation.py
  • docs/ENVIRONMENT_VARIABLES.md
  • scripts/audit_relevance.py
  • scripts/rescore_relevance.py
  • tests/test_consolidation_engine.py

✏️ Tip: You can disable in-progress messages and the fortune message in your review settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch exp/78-decay-fix

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added the enhancement New feature or request label Mar 2, 2026
@jack-arturo jack-arturo merged commit 3fce4ce into main Mar 2, 2026
6 of 7 checks passed
@jack-arturo jack-arturo deleted the exp/78-decay-fix branch March 2, 2026 19:00
jack-arturo added a commit that referenced this pull request Mar 7, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.14.0](v0.13.0...v0.14.0)
(2026-03-07)


### Features

* **config:** add QDRANT_HOST + QDRANT_PORT as alternative to QDRANT_URL
([#112](#112))
([0871904](0871904))
* **docker:** Add Docker build workflow
([#98](#98))
([39bf6e7](39bf6e7))


### Bug Fixes

* **benchmarks:** handle possessive speaker names in LoCoMo
([#116](#116))
([abcbcca](abcbcca))
* **consolidation:** reduce decay rate, add importance floor, filter
archived memories
([#78](#78))
([#105](#105))
([3fce4ce](3fce4ce))
* handle smart apostrophes in recall entity extraction
([#115](#115))
([05b4daa](05b4daa))
* harden MCP bridge resilience, adopt stateless transport, and update
cross-client docs
([#114](#114))
([ec88da6](ec88da6))
* **qdrant:** prevent silent vector dimension mismatch, set Voyage as
recommended default
([#108](#108))
([5f88105](5f88105))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

consolidation: Decay running but not affecting recall — archive/delete thresholds disabled, relevance approaching zero

1 participant