Skip to main content

HyperMEM - AI memory layer

judge-classify · store verbatim · hybrid semantic recall · live world-state · LLM-agnostic · local-first · introspectable

CI PyPI License: Source-Available Python 3.10+ Ollama / OpenAI / Anthropic

Install · Proof · How it works · API · License


HyperMEM is the memory layer between "chat" and "a character that remembers you." It watches a conversation, decides what is worth remembering, stores it verbatim, and later injects the relevant memories back into the context window, so an AI companion can recall a fact told 10,000 messages ago as reliably as one from yesterday, without a growing context and without remembering the wrong things.

It is LLM-agnostic (Ollama, OpenAI, Anthropic, or any OpenAI-compatible endpoint) and ships with a Python engine, a REST server, live world-state tracking (worldIDA), and JSON persistence.

It is also register-agnostic: the judge classifies, the store is verbatim, and worldIDA tracks physical state. None of it filters or reshapes content, so it serves every roleplay type identically: SFW, suggestive, explicit. A companion app never has to run two memory stacks.

What it does

  • Judge-classify - the fact-checker decides what matters (JSON, robustly extracted) but never writes the memory text. Your words are the memory.
  • Verbatim store - the user's message is stored intact (capped at max_memory_chars), so the exact tokens survive for recall. No paraphrase drift.
  • Hybrid semantic recall - embedding + lexical + importance + recency, budgeted for the context window. No LLM re-ranking of the whole list.
  • Type-aware lifecycle - a newer fact about the same subject supersedes the old one; episodic events consolidate into durable knowledge; decay archives what stops mattering.
  • Live world-state (worldIDA) - one compact physical state object per session (scene, positions, physical state, feasibility), fully rewritten every turn, injected in full. Narrative time (time of day, elapsed story days) gets its own block.
  • Provenance - for any memory and any query, the live score breakdown. No magic, no black box.
  • REST + Python - same engine over HTTP (hypermem-server) or inline.
  • Local-first - runs against a local Ollama; your data stays on your machine.

How it works (30 seconds)

 Your companion app
   (chat bot, game, CLI, REST client, your own code...)
        |   messages (the conversation)
        v
    +------------------------------------------------------------------+
    |  HyperMEM   (runs locally, your data stays here)                 |
    |  --------------------------------------------------------------  |
    |  Judge (classify)  ->  Verbatim store  ->  Lifecycle             |
    |       (what matters)    (your words)      (supersede/consolidate)|
    |                                                                    |
    |  Recall (hybrid score)  ->  Inject into context  <-  worldIDA    |
    |       (embedding+lexical+                                        |
    |        importance+recency)                                        |
    +------------------------------------------------------------------+
        |   relevant memories + world state
        v
 LLM provider  (Ollama - OpenAI - Anthropic - any OpenAI-compatible)
  • Judge decides what is worth remembering (importance, type, subject, keywords) without rewriting it.
  • Verbatim store keeps the exact words, so recall can match them later.
  • Lifecycle supersedes changed facts, consolidates episodic events, and decays what stops mattering.
  • Recall ranks by a hybrid score and injects only what fits the context budget.
  • worldIDA tracks the live physical scene state, injected in full every turn; narrative time (morning/evening, elapsed days) rides alongside in its own block.

Get started (60 seconds)

# 1 - Install
pip install hypermem            # core (any LLM via Ollama/OpenAI/Anthropic)
pip install "hypermem[server]"  # + REST server (fastapi, uvicorn)
# or, from source:
# git clone https://github.com/4biddencode/hypermem.git && cd hypermem && pip install -e .

# 2 - Point it at your LLM (default: Ollama, qwen2.5:7b on localhost:11434)
ollama serve                # if you haven't already

# 3 - Run the demo (real model, real numbers, no mocks)
python examples/demo.py

HyperMEM demo - real model, real output
Live: 8 facts planted, 40 filler messages, 8/8 recall, a changed fact superseded, provenance, worldIDA. Real Ollama, no mocks.

Or use it inline:

import asyncio
from hypermem import HyperMEM

hm = HyperMEM()  # defaults: Ollama, qwen2.5:7b on localhost:11434

async def main():
    # HyperMEM auto-tags important details as they arrive, stored verbatim
    await hm.add_message("user", "My name is Emanuel, I live in Vienna")
    await hm.add_message("user", "I'm planning a hike in the Alps next week")

    # Later, the relevant memories come back, even with different wording
    ctx = await hm.get_context("Where do I live?")
    print(ctx)

    # Why did that surface? Live score breakdown, no magic.
    await hm.explain_recall("Where do I live?", hm.memories()[0]["id"])

asyncio.run(main())

Output:

[RELEVANT MEMORIES]
- My name is Emanuel, I live in Vienna (importance: 100%)
[/RELEVANT MEMORIES]

Put ctx into your system prompt and your AI now answers with facts it was never given in the visible chat history.

Proof

Numbers are from the real benchmark (benchmarks/full_suite.py) against a real model (Ollama, qwen2.5:7b). No mocks, no cherry-picking. Low is better for latency, high is better for recall and contradiction handling.

Metric Result What it means
Recall @ 100 msgs ~0.9+ of 8 planted facts, ~7-8 come back after 40 filler messages
Paraphrase ~0.9+ "Where do I live?" still finds "my name is Emanuel, I live in Vienna"
Contradiction: new wins 1.0 a changed fact supersedes the old one, deterministically
Contradiction: stale leak 0.0 the superseded memory never resurfaces in recall
Judge latency ~1.4 s classify one message (LLM call, local model)
Recall latency ~0.2-0.5 s hybrid score, budgeted for the context window
worldIDA update ~3 s one compact state object, fully rewritten per turn

The point of the tables: HyperMEM does not hope to remember the right things - it is measured, and the numbers hold up across a real conversation.

When to use it

  • AI companions / roleplay - give the character a persistent memory of the user and the story, without a growing context window.
  • Chat agents & assistants - remember user preferences, facts, and project context across sessions.
  • Games with a narrative - the NPC remembers what happened, and what you told it.
  • Anything that talks to an LLM over multiple turns and wishes it could remember.

Integrations

HyperMEM is a library and a small REST server, not a plugin you install into a host app. You wire it in yourself, in a few lines:

  • Python - from hypermem import HyperMEM, then add_message / get_context.
  • REST - run hypermem-server, then:
    • POST /sessions - create a conversation
    • POST /sessions/{id}/messages - feed a message
    • GET /sessions/{id}/context?message=... - get relevant memories
    • GET /sessions/{id}/memories/{id}?query=... - provenance (why it surfaced)

Any language that can do HTTP can use HyperMEM. The server is stateless except for JSON files on disk, so you can run one instance for many conversations.

What's inside

  • hypermem/ - the engine
    • engine.py - the pipeline (judge -> store -> lifecycle -> recall -> context)
    • llm.py - robust JSON extraction, provider transport
    • world_ida.py - live world-state tracking
    • server.py - REST server
    • types.py - config, memory, persona
  • examples/demo.py - a real demo (facts planted, filler turns, recall)
  • benchmarks/ - the honest numbers, reproducible
  • tests/ - hermetic, no network

REST server

Run it, point any HTTP client at it, done:

pip install -e ".[server]"
hypermem-server --port 8080 --llm-provider ollama --llm-model qwen2.5:7b
# create a session
curl -X POST localhost:8080/sessions -d '{}'

# feed a message (judge decides if it matters, stores it verbatim)
curl -X POST localhost:8080/sessions/session_123/messages \
  -H 'content-type: application/json' \
  -d '{"role":"user","content":"My name is Emanuel, I live in Vienna"}'

# later, ask for relevant memories
curl "localhost:8080/sessions/session_123/context?message=Where%20do%20I%20live?"

Sessions are persisted as JSON on disk (.hypermem_data/ by default), so the server survives restarts. No database, no external service.

worldIDA (live world-state)

One compact state object per session tracking only the physical world - where the scene is, how each character is sitting, exactly where they are, whether a described action is physically possible. Fully rewritten every turn and injected in full. It is the "here and now" that episodic memories are too slow to capture:

{
  "scene": {"location": "tavern", "sub_location": "corner booth",
            "ongoing_action": "drinking ale"},
  "user": {"physical_state": "seated at the table", "position": "left of the booth"},
  "character": {"physical_state": "leaning forward", "position": "across from you"},
  "meta": {"physically_possible": true}
}

Emotional/social state (mood, relationship) is deliberately not tracked - worldIDA is physical-only. Narrative time (time of day + how many in-story days have passed, via a monotonic counter) is a separate [NARRATIVE TIME] context block, so the AI still knows it's morning of day 3 without polluting the physical state.

Persona isolation

Each HyperMEM instance holds its own memories, its own world-state, and its own persona. Two sessions never share memory unless you wire them to. The persona (name, description, traits, backstory, boundaries) is stored with the session and injected with context, so the same engine can power two very different characters without cross-contamination.

Configuration

Everything is configurable via HyperMemConfig (Python) or CLI flags (server). The important ones:

Option Default What it does
llm_provider auto ollama | openai | anthropic
llm_model qwen2.5:7b which model judges / recalls
llm_endpoint http://localhost:11434 provider base URL
auto_tag_threshold 0.4 minimum importance to store a memory
max_active_memories 100 cap on active (non-archived) memories
max_memory_chars 1000 verbatim content cap per memory
embedding_provider auto ollama | openai | none

API

The public surface is small on purpose. Everything else is internal.

Python

hm = HyperMEM(config)                      # engine, one per session

await hm.add_message(role, content)        # judge -> store -> lifecycle -> recall
await hm.remember(content, memory_type)    # store a memory directly
await hm.recall(query)                     # rank memories for a query
await hm.get_context(message)              # recall, formatted for the context window
await hm.explain_recall(query, memory_id)  # live score breakdown (provenance)

hm.memories()                              # list active memories
hm.set_persona(Persona(...))               # persona for this session
await hm.update_world_ida(user, ai)        # refresh world-state

hm.save(path) / hm.load(path)              # JSON persistence

REST

Method Endpoint Purpose
POST /sessions create a session
GET /sessions list sessions
DELETE /sessions/{id} delete a session
POST /sessions/{id}/messages feed a message
POST /sessions/{id}/remember store a memory directly
GET /sessions/{id}/recall?query= rank memories
GET /sessions/{id}/context?message= get context for a message
GET /sessions/{id}/memories list memories
GET /sessions/{id}/memories/{id}?query= provenance
PUT /sessions/{id}/persona set persona
GET /sessions/{id}/world-ida get world-state
POST /sessions/{id}/world-ida/update update world-state
GET /health liveness

Repo layout

hypermem/
  engine.py        # the pipeline
  llm.py           # provider + robust JSON
  world_ida.py     # live world-state
  server.py        # REST server
  types.py         # config, memory, persona
examples/
  demo.py          # real, reproducible demo
benchmarks/
  full_suite.py    # the numbers in "Proof"
tests/             # hermetic, no network

Contributing

HyperMEM is source-available. You are welcome to read it, run it, and contribute fixes and improvements. Please open an issue or PR - see CONTRIBUTING for the details, and the license below for what you can and cannot do with the code.

License

Source-Available License - you can read, run, and modify the code for your own use, and contribute back. Redistributing a competing hosted service built on it requires attribution. See the full license for the exact terms.

HyperMEM

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hypermem-1.0.2.tar.gz (48.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hypermem-1.0.2-py3-none-any.whl (51.0 kB view details)

Uploaded Python 3

File details

Details for the file hypermem-1.0.2.tar.gz.

File metadata

  • Download URL: hypermem-1.0.2.tar.gz
  • Upload date:
  • Size: 48.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for hypermem-1.0.2.tar.gz
Algorithm Hash digest
SHA256 1707045d17a72e7b14b5f61ef4e8c499cf9bce7f3b088260cd2f89aadddf5878
MD5 ef4d25b3394a4a1ff8b7dfb2f42124af
BLAKE2b-256 cb40602b154b999440db7933574b7fa5344892ea5154db9cca9f2fca34c3e51c

See more details on using hashes here.

Provenance

The following attestation bundles were made for hypermem-1.0.2.tar.gz:

Publisher: publish.yml on 4biddencode/hypermem

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hypermem-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: hypermem-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 51.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for hypermem-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 a3e3664a40104252f654acd83e8ca6beb9d74983ecc261d86bb7c416c883fbf2
MD5 b68255bcae2e3b63c6388bb119e913f7
BLAKE2b-256 2a3a84bfe2f7d1e7793f8a3e6a39201617bbb0d79d15a90072e4ee3be3c7e250

See more details on using hashes here.

Provenance

The following attestation bundles were made for hypermem-1.0.2-py3-none-any.whl:

Publisher: publish.yml on 4biddencode/hypermem

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.0.2 This release

2 files

1.0.1

2 files

1.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page