Metadata-Version: 2.4
Name: relational-memory
Version: 2.1.0
Summary: A relationship-aware memory layer for LLM chatbots — models the relationship, not just facts
Author-email: Florian Keusch <florian@keusch.wien>
License: # Big Time Public License
        
        Version 2.0.1
        
        <https://bigtimelicense.com/versions/2.0.1>
        
        ## Purpose
        
        These terms let you use and share this software for noncommercial purposes and in small business for free, while also guaranteeing that paid licenses for big businesses will be available on fair, reasonable, and nondiscriminatory terms.
        
        ## Acceptance
        
        In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
        
        ## Noncommercial Purposes
        
        You may use the software for any noncommercial purpose.
        
        ## Personal Uses
        
        Personal use for research, experiment, and testing for the benefit of public knowledge, personal study, private entertainment, hobby projects, amateur pursuits, or religious observance, without any anticipated commercial application, count as use for noncommercial purposes.
        
        ## Noncommercial Organizations
        
        Use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization, or government institution counts as use for noncommercial purposes, regardless of the source of funding or obligations resulting from the funding.
        
        ## Small Business
        
        You may use the software for the benefit of your company if it meets all these criteria:
        
        - had fewer than 20 total individuals working as employees and independent contractors at all times during the last tax year
        
        - earned less than $1,000,000 total revenue in the last tax year
        
        - received less than $1,000,000 total debt, equity, and other investment in the last five tax years, counting investment in predecessor companies that reorganized into, merged with, or spun out your company
        
        All dollar figures are United States dollars as of 2019. Adjust for them inflation according to the United States Bureau of Labor Statistics' consumer price index for all urban consumers, United States city average, for all items, not seasonally adjusted, with 1982-1984=100 reference base.
        
        ## Big Business
        
        You may use the software for the benefit of your company:
        
        - for 128 days after your company stops qualifying under Small Business
        
        - indefinitely, if the licensor or their legal successor does not offer fair, reasonable, and nondiscriminatory terms for a commercial license for the software within 32 days of written request and negotiate in good faith to conclude a deal
        
        ## How to Request
        
        If this software includes an address for the licensor or an agent of the licensor in a standard place, such as in documentation, software package metadata, or an "about" page or screen, try to request a fair commercial license at that address. If this package includes both online and offline addresses, try online before offline. If you can't deliver a request that way, or this software doesn't include any addressees, spend one hour online researching an address, recording all your searches and inquiries as you go, and try any addresses that you find. If you can't find any addresses, or if those addresses also fail, that counts as failure to offer a fair commercial license by the licensor under Big Business.
        
        ## Fair, Reasonable, and Nondiscriminatory Terms
        
        Fair, reasonable, and nondiscriminatory terms may license the software perpetually or for a term, and may or may not cover new versions of the software. If the licensor advertises license terms and a pricing structure for generally available commercial licenses, the licensor proposes license terms and a price as advertised, and a customer not affiliated with the licensor has bought a commercial license for the software on substantially equivalent terms in the past year, the proposal is fair, reasonable, and nondiscriminatory.
        
        ## Copyright License
        
        The licensor grants you a copyright license to do everything with the software that would otherwise infringe the licensor's copyright in it for any purpose allowed by these terms.
        
        ## Notices
        
        You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms or the URL for them above, as well as copies of any plain-text lines beginning with Required Notice: that the licensor provided with the software. For example:
        
        Required Notice: Copyright Florian Keusch / keusch.wien GmbH (https://keusch.wien)
        
        ## Patent License
        
        The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software.
        
        ## Fair Use
        
        You may have "fair use" rights for the software under the law. These terms do not limit them.
        
        ## No Other Rights
        
        These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses.
        
        ## Patent Defense
        
        If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
        
        ## Violations
        
        The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately.
        
        ## No Liability
        
        As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
        
        ## Definitions
        
        The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
        
        **You** refers to the individual or entity agreeing to these terms.
        
        **Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. **Control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
        
        **Your licenses** are all the licenses granted to you for the software under these terms.
        
        **Use** means anything you do with the software requiring one of your licenses.
        
Project-URL: Homepage, https://github.com/spectator81-png/relational-memory
Project-URL: Repository, https://github.com/spectator81-png/relational-memory
Project-URL: Issues, https://github.com/spectator81-png/relational-memory/issues
Keywords: llm,memory,relationship,chatbot,ai,sycophancy,ema,personality,context
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.20.0; extra == "anthropic"
Provides-Extra: openai
Requires-Dist: openai>=1.0.0; extra == "openai"
Provides-Extra: google
Requires-Dist: google-genai>=1.0.0; extra == "google"
Provides-Extra: all
Requires-Dist: anthropic>=0.20.0; extra == "all"
Requires-Dist: openai>=1.0.0; extra == "all"
Requires-Dist: google-genai>=1.0.0; extra == "all"
Dynamic: license-file

# Relational Memory

Memory systems make LLMs remember facts about you. This one models the *relationship* — and uses it to push back when you need it.

## The Problem

Most AI memory stores information *about* you: your name, your preferences, your past requests. The more it remembers, the better it gets at telling you what you want to hear. Memory makes sycophancy worse, not better.

What's missing is the thing that makes a good friend useful: knowing *how to be with you*. When to push, when to back off, when to call bullshit. That's not a fact you store — it's a relationship you build.

## See the Difference

Same model (Claude), same prompt. One has relational memory from 6 prior sessions, one doesn't.

### 1. Same question, different instinct

**User:** "I feel lost. Lots of ideas, don't know which is worth pursuing."

**Without memory:**
> I know that feeling. Write all your ideas down. Ask yourself: Which would still excite me after the spark fades? Pick the one with least resistance. Give yourself two weeks.

**With memory:**
> I know that about you — you don't think in small categories, and that makes prioritizing harder. But "which one is worth it" might be the wrong question. It pretends there's an objectively right answer. Which idea won't leave you alone at night?

*One gives a framework. The other challenges the question itself.*

### 2. When the user deflects

**Without memory — user corrects the bot:**
> **User:** "You didn't even ask me about the actual idea."
> **Bot:** "You're right — sorry! Tell me, I'm listening."

**With memory — user tries to change the subject:**
> **User:** "Why do you always ask me so much? I'd like to learn about you."
> **Bot:** "Fair question. But I notice it comes exactly where it gets uncomfortable. I just asked where you break off — and instead of going there, you want to flip the focus. Deal: I'll answer one question about me. Then we go back to yours."

*Without memory, the bot follows. With memory, it names the pattern — but with respect, not judgment.*

### 3. Persistence

Two exchanges later, the user deflects again:

> **User:** "Is this better for you than other bots that forget everything?"
> **Bot:** [answers thoughtfully, then:] "And now I notice you've elegantly steered me away from your question for the second time. You're good at that. Where do you break off?"

*A generic bot follows wherever the user leads. This one remembers what it was asking — and comes back.*

The full A/B transcript (fictionalized persona, real dynamics): [ab_test.md](docs/ab_test.md)

## Try It

```bash
pip install relational-memory[anthropic]
export ANTHROPIC_API_KEY=sk-ant-...
relational-memory
```

Chat uses **Claude Opus** by default. Signal extraction and sleep-time condensation use **Haiku** (cheap, fast). You can switch the chat model via `LLMClient` or use `--provider openai` for GPT-4o.

Chat for a few sessions. After ~2 sessions the tone starts adapting. After 5, the bot generates narrative layers (a distilled portrait, behavioral patterns, relationship turning points) and the difference becomes obvious.

Options:
```bash
relational-memory --mode flat       # no memory (A/B comparison)
relational-memory --user alex       # separate memory per user
relational-memory --provider openai  # use GPT-4o instead
relational-memory --provider google  # use Gemini instead
relational-memory --provider local   # use local model (Ollama etc.)
```

### Install with your preferred provider

```bash
pip install relational-memory[anthropic]  # Claude (default)
pip install relational-memory[openai]     # GPT-4o / GPT-4o-mini
pip install relational-memory[google]     # Gemini
pip install relational-memory[all]        # all providers
pip install relational-memory             # core only (bring your own SDK)
```

The core library has zero dependencies — provider SDKs are optional. Install what you need.

## What Happens Over Time

**Session 1:** You chat normally. When you exit, a second LLM reads the entire conversation and scores the relationship on 7 dimensions — how formal were you, how warm was the exchange, did you handle pushback or avoid it? No configuration, no sliders, no labeling. The model figures out your style by analyzing its own interaction with you. Your relationship vector starts moving from neutral (all 0.5) toward your actual dynamic.

**Sessions 2-4:** Each session, the model re-evaluates and the vector shifts further via EMA (exponential moving average — recent sessions matter more, but old ones don't vanish). If you're consistently informal, formality drops. If you handle disagreement well, resilience rises. The vector is injected into the system prompt, so the bot adapts its tone, directness, and humor automatically.

**Session 5:** The sleep-time agent runs automatically. It reads the full signal history and generates three narrative layers: a portrait of who you are, behavioral if-then patterns it's learned, and key moments that shaped the relationship. These are stored as markdown files you can read and edit.

**Session 6+:** The bot now has both the vector AND the narrative context. It doesn't just know you're informal (formality: 0.36) — it knows that "when AI gets intellectually shallow, you push back with sharper questions" and that "you show vulnerability without treating it as weakness." That's what makes the difference in the [A/B test](docs/ab_test.md).

## How It Works

```
You ──→ Chat CLI ──→ LLM (streaming) ──→ Response
                          │
                    end of session
                          │
                    Signal Extraction:
                    A second LLM reads the conversation
                    and scores the relationship on 7 dimensions
                    (no human labeling — fully self-calibrating)
                          │
                    EMA update: vector = 0.9 * old + 0.1 * new
                          │
                    every 5 sessions:
                    Sleep-Time Agent condenses signal history
                    into narrative layers
```

**Three layers of memory** instead of a flat fact store. Most AI memory systems save discrete facts ("user likes Python", "user is from Berlin"). This one stores relationship knowledge as narrative — the way a close friend would describe you, not a database entry. The three layers have different lifespans, inspired by how human memory consolidation works during sleep:

| Layer | What it stores | Lifespan | Example |
|---|---|---|---|
| **Base Tone** | Distilled portrait of the user | Months | "Intellectually curious, low BS tolerance, vulnerable without seeing it as weakness" |
| **Patterns** | If-then behavioral rules | Weeks | "When AI gets intellectually shallow → pushes back with sharper questions" |
| **Anchors** | Relationship turning points | Permanent | "Asked directly whether AI is manipulating them — trust test" |

The layers are generated by a sleep-time agent that runs *between* sessions — like memory consolidation during sleep. It reads the signal history and distills it into narrative. Patterns that are no longer supported by recent data get dropped. Anchors stay unless they become irrelevant. The signal log gets trimmed to the last 20 entries. **Forgetting is a feature** — it forces compression and prevents the illusion of perfect recall.

Layer files are plain markdown in `~/.relational_memory/<user_id>/layers/` — you can open them, read what the AI "knows" about you, and edit them if something is wrong.

**The 7 dimensions:**

| Dimension | What it tracks | Low | High |
|---|---|---|---|
| Formality | Communication register | Casual, slang | Structured, professional |
| Warmth | Emotional closeness | Task-focused | Personal, affectionate |
| Humor | Role of humor | Serious throughout | Playful, dark humor |
| Depth | Intellectual/emotional depth | Surface-level | Philosophical, existential |
| Trust | Openness and vulnerability | Guarded | Shares unprompted |
| Energy | Conversational drive | Low-energy, brief | Engaged, expansive |
| Resilience | Capacity for discomfort | Fragile, needs gentle framing | Can handle confrontation |

The key insight: **the model calibrates itself**. After each session, an LLM-as-Judge analyzes the conversation and extracts all 7 values — no human labels, no user configuration. The vector is then injected into the next session's system prompt (~600 tokens), where the model uses it to calibrate tone, directness, and how hard to push. High resilience + high trust = the bot will call you on your bullshit. Low resilience = it frames challenges as questions.

## What This Is (and Isn't)

This is a **working prototype** (v2.1). It's tested with 2 independent testers over 16 sessions, and the effect is real — but it's honest to name the limits:

- **Tested with 2 people over 16 sessions total.** The dynamics are real, but n=2. I built this for myself and it works. Whether it generalizes broadly is an open question.
- **~900 lines of Python.** No framework, no database, no infrastructure. Markdown files and JSON. This is intentional — the idea matters more than the engineering.
- **Requires API calls.** Signal extraction uses a small model (Haiku/Mini/Flash) after each session. Sleep-time condensation runs every 5 sessions. Both cost fractions of a cent.
- **4 LLM providers.** Anthropic (Claude), OpenAI (GPT-4o), Google (Gemini), and any OpenAI-compatible local model (Ollama, llama.cpp, vLLM).

## The Idea Behind It

Most memory systems optimize for *recall* — remembering what the user said. This one optimizes for *relationship quality* — knowing how to be with someone.

The concept draws from:
- **Implicit Relational Knowing** (Lyons-Ruth, 1998) — the psychological concept of "knowing how to be with" someone, distinct from declarative memory
- **The sycophancy problem** — LLMs systematically agree with users, and personalization makes it worse (Sharma et al., 2023; Anthropic, 2024)
- **Memory consolidation** — the three-layer architecture mirrors how human memory works: episodic details consolidate into patterns and identity over time

The core thesis: **Relational memory gives the AI the confidence to be uncomfortable.** Not because it's programmed to disagree, but because it knows this specific user can handle it — and that honest friction is more valuable than comfortable agreement.

### Why these 7 dimensions?

The dimensions aren't arbitrary — they were derived by analyzing 6 established psychological models (IPC, SASB, PRQC, Russell Circumplex, WAI, EHARS):

- **4 directly derivable** from existing literature: Warmth (IPC Communion), Energy (Russell Arousal), Trust (PRQC Trust), Depth (PRQC Intimacy)
- **1 context-adapted:** Formality replaces the IPC Dominance/Agency axis — because in human-AI dyads, power asymmetry is structural, not dynamic. What varies is the behavioral register of that asymmetry.
- **2 novel:**
  - **Humor** — extensively researched as a relationship factor (Martin et al., 2003; Tan et al., 2023) but never operationalized as a trackable relationship dimension
  - **Resilience** — the core contribution. Derived from Bowlby's Secure Base theory and Gottman's Repair Attempts research, this is the dimension that operationalizes anti-sycophancy: *how much honest friction can this relationship handle?*

Each dimension maps directly to a behavioral decision the AI makes every turn: formal or casual? joke or stay serious? push back or agree? 7 is the minimum number of distinct behavioral decisions needed — not a taxonomy, but a decision space.

## References

- Lyons-Ruth, K. (1998). Implicit relational knowing: Its role in development and psychoanalytic treatment. *Infant Mental Health Journal*, 19(3), 282-289.
- Sharma, M., et al. (2023). Towards Understanding Sycophancy in Language Models. *arXiv:2310.13548*.
- Leary, T. (1957). *Interpersonal Diagnosis of Personality*. Ronald Press.
- Fletcher, G., Simpson, J., & Thomas, G. (2000). The measurement of perceived relationship quality components. *Personality and Social Psychology Bulletin*, 26(3), 340-354.
- Russell, J. A. (1980). A circumplex model of affect. *Journal of Personality and Social Psychology*, 39(6), 1161-1178.
- Martin, R. A., et al. (2003). Individual differences in uses of humor and their relation to psychological well-being. *Journal of Research in Personality*, 37(1), 48-75.
- Gottman, J. M. (1999). *The Marriage Clinic: A Scientifically Based Marital Therapy*. Norton.
- Bowlby, J. (1988). *A Secure Base: Parent-Child Attachment and Healthy Human Development*. Basic Books.

## Project Structure

```
relational_memory/        # library package (~900 lines)
  __init__.py             # public API (24 exports)
  __main__.py             # CLI entry point
  vector.py               # 7D EMA vector, dual-alpha
  llm.py                  # 4 providers: Anthropic, OpenAI, Google, Local
  signals.py              # signal extraction v2 via LLM-as-judge
  layers.py               # three-layer markdown storage with versioning
  context.py              # layers + vector + drift warnings → system prompt
  sleep.py                # sleep-time condensation with versioned backup
  drift.py                # drift detection and baseline tracking
  truncation.py           # sliding-window message truncation
  storage.py              # secure file I/O with filesystem permissions
  prompts/                # LLM prompts (signal extraction, context template, condensation)
docs/
  ab_test.md              # full A/B transcript (fictionalized)
```

Runtime data is stored in `~/.relational_memory/<user_id>/`.

## License

[Big Time Public License 2.0.1](https://bigtimelicense.com/versions/2.0.1) — free for personal, educational, non-commercial use and small businesses (<20 employees, <$1M revenue). Commercial use by larger companies requires a separate license — contact florian@keusch.wien.

---

*After ~5 sessions the bot starts to know when to push back and when to shut up. I don't know if this works for everyone — I built it for myself and it works for me. If you try it and it does something for you, I'd love to hear about it.*
