Counteract positive recall bias in memory-augmented AI systems. Zero dependencies.
Project description
anti-resonance
Counteract positive recall bias in memory-augmented AI systems. Zero dependencies.
Install
pip install anti-resonance
Quick Start
from anti_resonance import ensure_negative_ratio
# Your RAG/memory system returned 10 results — mostly wins
results = [
{"text": "Trade won +$150", "pnl": 150, "score": 0.9},
{"text": "Trade won +$80", "pnl": 80, "score": 0.8},
{"text": "Trade won +$200", "pnl": 200, "score": 0.85},
{"text": "Trade won +$50", "pnl": 50, "score": 0.7},
{"text": "Trade won +$120", "pnl": 120, "score": 0.75},
]
# Losses from your full memory pool
candidates = [
{"text": "Trade lost -$90 (SL hit in ranging market)", "pnl": -90, "score": 0.6},
{"text": "Trade lost -$200 (gap against position)", "pnl": -200, "score": 0.4},
{"text": "Trade lost -$45 (spread widened at news)", "pnl": -45, "score": 0.5},
]
# Force at least 20% losses into the context window
balanced = ensure_negative_ratio(
results, candidates,
min_negative_ratio=0.2,
score_key="score", # score-aware: replaces lowest-score wins
)
The agent now sees both wins AND losses before making its next decision.
The Problem: Parametric-External Memory Resonance
When an LLM-based agent retrieves memories to inform a decision, two bias sources resonate with each other:
-
Parametric bias (inside the LLM): Language models trained on internet text have a built-in optimism bias. Success stories, best practices, and positive outcomes are overrepresented in training data.
-
External memory bias (in the retrieval system): Similarity-based retrieval (vector search, embedding lookup) clusters positive outcomes together. Winning trades look alike ("strong momentum", "breakout confirmed"). Losing trades are diverse and scattered ("gap down", "spread spike", "regime change") — they don't cluster, so they rank low in similarity search.
When the LLM's parametric optimism meets a one-sided positive context window, the biases amplify each other. The model becomes dangerously overconfident because both its training and its retrieved evidence agree.
This is Parametric-External Memory Resonance — a feedback loop between the model's internal beliefs and the retrieval system's structural bias toward positive outcomes.
The Fix
Break the resonance by forcing counterexamples into the context window. anti-resonance does this at the post-retrieval stage:
Query → Retrieval → [anti-resonance] → LLM
↑
Force 20% negatives
into the result set
The algorithm is simple:
- Count negative items in top-K results
- If ratio >= threshold → return unchanged
- Otherwise → replace lowest-scoring positives with highest-scoring negatives from the candidate pool
- Re-sort by score
Score-aware replacement (v0.2.0) ensures you sacrifice the least-relevant positive items and inject the most-relevant negative ones.
API
ensure_negative_ratio(results, candidates, min_negative_ratio=0.2, negative_classifier=None, score_key=None)
| Parameter | Type | Default | Description |
|---|---|---|---|
results |
list[dict] |
required | Top-K retrieval results |
candidates |
list[dict] |
required | Full candidate pool |
min_negative_ratio |
float |
0.2 |
Minimum negative fraction [0.0, 1.0] |
negative_classifier |
Callable |
None |
Returns True for negative items. Default: item["pnl"] < 0 |
score_key |
str |
None |
Dict key for relevance score. Enables score-aware replacement |
Returns: New list (same length) with at least min_negative_ratio negatives.
ensure_negative_balance
Alias for ensure_negative_ratio (backward compatibility with TradeMemory).
Use Cases
Trading Memory
balanced = ensure_negative_ratio(
recalled_trades, all_trades,
min_negative_ratio=0.2,
score_key="owm_score",
)
# Agent sees losing trades alongside winners before deciding
RAG Pipelines
balanced = ensure_negative_ratio(
search_results, full_corpus,
negative_classifier=lambda doc: doc["sentiment"] < 0,
score_key="relevance",
)
# LLM sees failure cases alongside success stories
Customer Support
balanced = ensure_negative_ratio(
similar_tickets, all_tickets,
negative_classifier=lambda t: t["resolution"] == "unresolved",
)
# Agent considers unresolved similar cases, not just resolved ones
Related Work
-
FinMem (Yu et al., 2024) — FinMem: A Performance-Enhanced LLM Trading Agent with Layered Memory and Character Design. Identified the echo chamber problem in LLM trading agents where memory retrieval reinforces existing beliefs. arXiv:2311.13743
-
TradeMemory Protocol — Open-source trading memory layer where anti-resonance was first implemented. The
ensure_negative_balance()function in TradeMemory's hybrid recall pipeline is the production origin of this package. GitHub -
Building Anti-Resonance for AI Trading Agents (Sean, 2026) — DEV.to article explaining why RAG-based trading agents develop confirmation bias and how to fix it. DEV.to
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file anti_resonance-0.2.0.tar.gz.
File metadata
- Download URL: anti_resonance-0.2.0.tar.gz
- Upload date:
- Size: 7.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1788f086b6b8a7319f5d89ac7d6c2a01932adf581f6bd083ac4c88c8367e8953
|
|
| MD5 |
8f47c8a6cc96ac7f85847b1c2a601aa3
|
|
| BLAKE2b-256 |
28f476ce3766f3c439dba8ebccee19476158923be064e29068b37efa68908a66
|
Provenance
The following attestation bundles were made for anti_resonance-0.2.0.tar.gz:
Publisher:
publish.yml on mnemox-ai/anti-resonance
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
anti_resonance-0.2.0.tar.gz -
Subject digest:
1788f086b6b8a7319f5d89ac7d6c2a01932adf581f6bd083ac4c88c8367e8953 - Sigstore transparency entry: 1178424322
- Sigstore integration time:
-
Permalink:
mnemox-ai/anti-resonance@4366bdf09572234a426e7dd50c226d3626e62c49 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/mnemox-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4366bdf09572234a426e7dd50c226d3626e62c49 -
Trigger Event:
push
-
Statement type:
File details
Details for the file anti_resonance-0.2.0-py3-none-any.whl.
File metadata
- Download URL: anti_resonance-0.2.0-py3-none-any.whl
- Upload date:
- Size: 6.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
781ae1e4ea6c90d81a534f0ea95f3a121967e9942c1e41bc8cc61254b482bcc9
|
|
| MD5 |
2ceeda1202b80b100de719925af92b0b
|
|
| BLAKE2b-256 |
783b688ab9193be29a36d440b48477e2727807edbfcbb4d3feaac8cafde48f5d
|
Provenance
The following attestation bundles were made for anti_resonance-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on mnemox-ai/anti-resonance
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
anti_resonance-0.2.0-py3-none-any.whl -
Subject digest:
781ae1e4ea6c90d81a534f0ea95f3a121967e9942c1e41bc8cc61254b482bcc9 - Sigstore transparency entry: 1178424342
- Sigstore integration time:
-
Permalink:
mnemox-ai/anti-resonance@4366bdf09572234a426e7dd50c226d3626e62c49 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/mnemox-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4366bdf09572234a426e7dd50c226d3626e62c49 -
Trigger Event:
push
-
Statement type: