Skip to main content

DSPM — memory for LLM conversations that keeps your constraints

Dynamic Semantic Patch Memory, by Dhruv Dubey · Python package: dspm-memory · Repo: Kernl

PyPI version License: MIT Python 3.9+

pip install dspm-memory

Long chats drop the rule from turn 3 that everything else depends on. DSPM turns each turn into typed patches, protects constraints, decisions and revised values, and renders them under a fixed token budget. Training-free: no fine-tuning, just prompts and Python rules. Works with any OpenAI-compatible endpoint.


Headline numbers (v0.2.1, verified on live data)

24-turn fintech conversation, 648 raw tokens, 3 revisions tracked (JWT 15→30min, S3 1h→15min, CPU 70→60%), real Groq LLM:

Budget CRR TRR Context tokens
60 100% 93.1% 45
100 100% 81.9% 117
250 100% 59.3% 264
400 100% 36.1% 414
800 100% 0.6% 644

CRR = Critical Retention Rate. TRR = Token Reduction Rate (conversation-based). CRR = 100% is a structural guarantee, verified across budgets 59 to 5000 tokens.

Offline benchmark (v0.1.17, 7 hand-authored 40-turn dialogues, same model for extraction and judging):

Budget TRR CRR
150 66.8% 100%
250 82.8% 100%
400 72.4% 100%

Recognition: Poster accepted at CAICS 2026 (Indo-US Workshop on AI & Cybersecurity), organized by IISc Bengaluru and Argonne National Laboratory, funded by the U.S. Department of State.

Savings depend on conversation length. Short conversations compress very little. Recommended budget: 250–400 for best readability + compression balance.

Who it's for: agents and chatbots whose long conversations must not lose a constraint, a decision, or a revised value (support bots, coding agents, assistants that remember a user's hard rules across sessions).

Who it's not for: summarizing or answering questions over documents. See Known Limitations.


Quickstart

from openai import OpenAI
from dspm import DSPMMemory

llm = OpenAI(api_key="sk-...")   # any OpenAI-compatible endpoint
mem = DSPMMemory(budget=250, llm_client=llm, model="gpt-4o-mini")

mem.add_turn("user", "Always return JSON. Use POST /v1/items. Max fee 0.5%.")
mem.add_turn("assistant", "Webhook timeout set to 30 seconds.")

# Later: the webhook timeout is revised
mem.add_turn("user", "Webhook timeout updated to 10 seconds.")

print(mem.get_context(query="What must the contract remember?"))
print(mem.stats)

Illustrative output (exact wording varies by extraction model):

[DEC] Webhook timeout updated to 10 seconds (was 30)
[CON] Max fee 0.5%
[DEC] Use POST /v1/items
[CON] Always return JSON output.

No paid key? Use a free Groq tier or a local Ollama model:

# Groq (free tier available at console.groq.com)
llm = OpenAI(base_url="https://api.groq.com/openai/v1", api_key="gsk_...")

# Ollama (local, no key needed)
llm = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")

# Together AI
llm = OpenAI(base_url="https://api.together.xyz/v1", api_key="...")

Why it's different

  • Constraints and decisions are protected. [CON] and [DEC] patches are never dropped by dedup, fusion or pruning, and are selected first at render time.
  • Revisions supersede old values. Change a value mid-chat and the current one survives, with the lineage baked in as (was X).
  • Memory persists across chats. Save at the end of one chat, load at the start of the next, with no API cost for recall.
  • Fixed budget, predictable cost. You set the token budget; the rendered context stays inside it.
  • Universal CRR guarantee. CRR = 100% at any budget above the floor. Below the floor, raises BudgetTooSmallError instead of silently dropping criticals.

Universal CRR guarantee

from dspm.engine import DSPMEngine, BudgetTooSmallError

# Find the minimum safe budget for N critical patches
floor = DSPMEngine.min_budget_for_crr(22)   # → 59 tokens for 22 criticals

# Below the floor, raises a clear error instead of silently dropping
try:
    mem.set_budget(10)
    mem.get_context()
except BudgetTooSmallError as e:
    print(e)  # Budget 10 is below the absolute floor (59 tokens for 22 criticals)

5-stage compression ladder, which escalates only as needed:

Stage When triggered What it does
1. Numeric-trim Always Keeps numbers, units, acronyms; drops filler words
2. Iterative-trim Budget pressure Trims the longest critical one word at a time
3. Ultra-compact Tight budget Reduces each critical to key numbers only
4. Dense-merge Very tight Merges all criticals into one line
5. Ultra-dense Extreme Single line of space-separated tokens

Persistence: memory across chats and sessions

# Chat 1 — Monday
mem = DSPMMemory(budget=250, llm_client=llm, model="gpt-4o-mini")
mem.add_turn("user", "Building a budgeting app. Hard rules: must work offline, deadline Oct 20.")
mem.save("user_42_memory.json")

# Chat 2 — Thursday, new process
mem2 = DSPMMemory(budget=250, llm_client=llm, model="gpt-4o-mini")
mem2.load("user_42_memory.json")
mem2.get_context(query="What were my hard rules?")
# → [CON] must work offline
# → [CON] deadline Oct 20   ← recalled from Chat 1, zero API cost

mem2.add_turn("user", "The deadline moved to November 5.")
# → Oct 20 is superseded. November 5 replaces it.

Persistence safety: writes are atomic, and load(path, strict=True) raises CorruptNotebookError on corrupt files.


How it works

Raw conversation (648 tokens, 24 turns)
        ↓
Semantic extraction → 39 patches, 20 critical
        ↓
7-stage compression pipeline
        ↓
Compressed context (264 tokens @ budget 250) — 100% of criticals selected

Pipeline: fingerprint dedup → slot fusion → delta encoding → causal pruning → utility scoring → shadow selection → adaptive budget allocation.


Patch types

Type Tag Critical? Description
constraint [CON] Yes Non-negotiable requirements (deadlines, limits, compliance rules)
decision [DEC] Yes Speaker value directives ("set timeout to 30 seconds")
code [CODE] No Implementation detail
equation [EQ] No Formulas and numeric results
entity [ENT] No Named things
structure [STR] No Schemas and workflows

Regulatory and compliance requirements (PCI-DSS, HIPAA, GDPR, SOC 2, ISO 27001, FedRAMP) are classified as constraints by the extractor prompt.


Stats and metrics

print(mem.stats)
Key Description
turns Number of conversation turns added
total_patches Active patches in the store
critical_total Constraint + decision patches (protected)
critical_selected Critical patches delivered in the last get_context()
crr Critical Retention Rate: % of extracted criticals delivered
trr_by_conversation Token Reduction Rate, conversation-based. Use this for savings
budget Current token budget
conversation_tokens Raw turn text fed to add_turn()
patch_tokens Tokens in the extracted patches
context_tokens Tokens in the delivered context
llm_calls Total LLM calls made
llm_errors Total LLM errors

Testing

Run offline tests (no API key needed):

python tests/verify_crr.py
python tests/test_universal_budgets.py

Run live tests (API key required):

# Windows PowerShell
$env:GROQ_API_KEY = "gsk_..."

python tests/small_live_test_budgets.py   # 10-turn REST API conversation
python tests/large_live_test_budgets.py   # 24-turn fintech + 3 revisions

See tests/README.md for expected output and reproduction instructions.


API reference

DSPMMemory(budget, llm_client, model)

Parameter Type Default Description
budget int 400 Maximum tokens in the compressed output
llm_client OpenAI-compatible None Any sync OpenAI-compatible client
model str "gpt-4o-mini" Model used for patch extraction

Methods

Method Description
add_turn(role, text) Add a conversation turn. Returns extracted patches.
get_context(query="") Returns compressed context string.
set_budget(budget) Update the token budget.
save(path) Persist memory to JSON (atomic write).
load(path, strict=False) Load a saved memory file.
reset() Clear all memory.

Properties

Property Description
memory.stats Dict with token counts, patch counts, CRR, TRR and LLM telemetry
memory.critical_patches List of critical patches in memory
memory.all_patches List of every patch in memory

Advanced API

from dspm import DSPMEngine, extract_patches, merge_into_memory, SemanticPatch
from dspm.engine import BudgetTooSmallError

Repository layout

.
├── dspm/
│   ├── __init__.py      # public API
│   ├── patch.py         # SemanticPatch structure
│   ├── engine.py        # DSPMEngine v4.5 — 7-stage pipeline + CRR guarantee
│   ├── extractor.py     # LLM-based patch extraction
│   ├── client.py        # LLMClient + provider auto-detection
│   └── memory.py        # DSPMMemory high-level wrapper
├── tests/
│   ├── verify_crr.py              # quick CRR check
│   ├── test_universal_budgets.py  # offline sweep, 17 budgets
│   ├── small_live_test_budgets.py # 10-turn live test
│   ├── large_live_test_budgets.py # 24-turn live test with 3 revisions
│   └── README.md                  # reproduction instructions
├── pyproject.toml
├── README.md
└── LICENSE

Known Limitations

  • Small budgets under-deliver readability. At budget 60, context is trimmed to bare numbers. CRR = 100% but human readability suffers. Recommended minimum for readable output: budget 100.
  • Per-turn extraction cap. The extraction prompt allows at most 1 constraint and 1 decision per turn. If a single message states several hard rules, split them across turns.
  • Revision matching is rule-based. Numeric, day-name and acronym-bridged revisions are handled. Other free-text revisions may coexist with stale values.
  • Extraction depends on the LLM. Quality varies by model and domain. A constraint the extractor misses is not protected.
  • No async support yet. add_turn() is synchronous. Planned for v0.3.0.
  • Document QA. DSPM is designed for conversations, not document compression.
  • Self-judged offline benchmark. Same model family for extraction and judging; not independently replicated. Run live tests with your own data using tests/large_live_test_budgets.py.

Paper

DSPM: A Critical-Retention Approach to Long-Context Memory Compression for LLM Conversations Dhruv Dubey, 2026 · Zenodo: 10.5281/zenodo.19438636

Recognition: Poster accepted at CAICS 2026 (Indo-US Workshop on AI & Cybersecurity), jointly organized by IISc Bengaluru and Argonne National Laboratory, funded by the U.S. Department of State.


Feedback

Found a case where a constraint or revision is lost? Open an issue with the conversation and the budget you used.


License

MIT © 2026 Dhruv Dubey

Metadata

Release files for dspm-memory 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dspm-memory 0.2.2
File Size Uploaded Provenance Actions
dspm_memory-0.2.2.tar.gz 32.1 kB Without provenance Details for dspm_memory-0.2.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for dspm-memory 0.2.2
File Interpreter ABI Platform Actions
dspm_memory-0.2.2-py3-none-any.whl Python 3 none any Details for dspm_memory-0.2.2-py3-none-any.whl

Total release size: 56.2 kB

Release files / dspm_memory-0.2.2.tar.gz

Download URL dspm_memory-0.2.2.tar.gz
Size 32.1 kB
Tags Source
SHA-256 checksum
How to use checksums
36892e0dbb2d9b846073fbd9714bbe883518f9b46bcead16b8abd8b823a4a0ce
BLAKE2b-256 checksum
How to use checksums
3f99b7e9f8f8574b3559f460da4831a39c4a7e4a8ccfe6cc31d61491df12c2e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.8

Release files / dspm_memory-0.2.2-py3-none-any.whl

Download URL dspm_memory-0.2.2-py3-none-any.whl
Size 24.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4a0ce5b3c3b75e350c205b7fa4d8e9ca6c6de339204948a92ce968c6f1386806
BLAKE2b-256 checksum
How to use checksums
67a3a2c92e5c6cbe4269776e7b6fb5a976f24590a73990d3713a793d7c4a3b74
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.8

Security for dspm-memory 0.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page