Emotional extension for AI companions โ memory triggers, relationship states, self-emotion.
Project description
affective-longing ๐ง ๐ซ
Emotional extension for AI companions โ beyond timing, into feeling.
Built on revive-companion (Poisson timing + Bayesian inference).
Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AffectiveLonging โ
โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Memory โ โ Relationship โ โ Emotion โ โ
โ โ โ โ โ โ โ โ
โ โ ChromaDB โ โ HMM โ โ VAD Model โ โ
โ โ Embeddings โ โ OU Process โ โ Valence โ โ
โ โ Similarity โ โ 6 Stages โ โ Arousal โ โ
โ โ โ โ โ โ Dominance โ โ
โ โโโโโโโโฌโโโโโโโโ โโโโโโโโฌโโโโโโโโ โโโโโโโโฌโโโโโโโโ โ
โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโ โ
โ โผ โ
โ tick() โ AffectiveResult โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ revive-companion (base) โ โ
โ โ Poisson Process โ InfoGain โ Bayesian โ Decision โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Three Layers
1. Memory โ Past triggers present
Store conversations as embeddings. When current context matches past memories, longing probability gets a boost.
engine.remember("ไฝ ๅๆฌขไธ้จๅคฉ", tags=["weather"])
engine.remember("ๆไปฌ็ฌฌไธๆฌก็็ตๅฝฑๆฏใๆ้
็ฉฟ่ถใ", tags=["movie"])
# Later...
result = engine.tick(context="ไปๅคฉไธ้จไบ")
# โ Triggers "ไฝ ๅๆฌขไธ้จๅคฉ" with similarity 0.988
# โ Longing boost: +15%
Theory: Sentence embeddings (all-MiniLM-L6-v2) + cosine similarity. Memory decay via Ebbinghaus forgetting curve.
2. Relationship โ 6-stage lifecycle
Models relationship dynamics through discrete state transitions (HMM) + continuous emotional drift (Ornstein-Uhlenbeck process).
่ฟฝๆฑ โ ็่ โ ็ญๆ โ ๅนณ็จณ
โ โ
โโโโโ ไฟฎๅค โ ๅทๆ โโโโ
engine.observe("affection") # intimacy +0.10
engine.observe("fight") # conflict +0.20, may โ ๅทๆ
engine.step_time(hours=24) # OU decay toward baseline
Theory:
- HMM: Hidden states (relationship stages), observed events (user actions). Transition matrix modulated by intimacy/conflict levels.
- Ornstein-Uhlenbeck: Mean-reverting stochastic process.
dX = ฮธ(ฮผ - X)dt + ฯdW. Models how intimacy/conflict drift toward baselines over time.
3. Emotion โ VAD model
AI companion's internal emotional state modeled as 3D vector (Valence, Arousal, Dominance). Mapped to 11 discrete emotions.
state = engine.emotion.current_state
# EmotionalState(๐ joy, V=+0.65, A=0.58, D=0.55)
| Dimension | Range | Meaning |
|---|---|---|
| Valence | -1 to +1 | Unhappy โ Happy |
| Arousal | 0 to 1 | Calm โ Excited |
| Dominance | 0 to 1 | Submissive โ Dominant |
Theory: Russell's Circumplex Model (1980) + Mehrabian's PAD model (1996). OU process for time decay, event-driven bumps for state changes.
Install
# Base (Poisson + Bayesian from revive-companion)
pip install affective-longing
# With memory support (sentence-transformers + chromadb)
pip install affective-longing[memory]
Quick Start
from affective_longing import AffectiveLonging
engine = AffectiveLonging(seed=42)
# 1. Store memories
engine.remember("ไฝ ๅๆฌขไธ้จๅคฉ", tags=["weather"])
engine.remember("ไฝ ่ฏด่ฟๆๅๆฌขๅ่่่็ณ", tags=["food"])
# 2. Observe events
engine.observe("reply_fast")
engine.observe("affection")
# 3. Let time pass
engine.step_time(hours=12)
# 4. Tick with context
result = engine.tick(context="ไปๅคฉไธ้จไบ")
print(f"Base probability: {result.base_probability:.1%}")
print(f"Memory trigger: {result.memory_trigger}")
print(f"Similarity: {result.memory_similarity:.3f}")
print(f"Boosted probability: {result.boosted_probability:.1%}")
print(f"Relationship: {result.relationship_stage.value}")
print(f"Emotion: {result.emotional_state.emoji} {result.emotional_state.emotion.value}")
if result.should_send:
send_message(result.prompt)
engine.record_send()
API Reference
AffectiveLonging
engine = AffectiveLonging(
memory_persist_dir="./companion_memory_db", # Where to store embeddings
relationship_seed=None, # For reproducibility
emotion_seed=None,
**kwargs # Passed to PoissonLove
)
Methods:
| Method | Description |
|---|---|
remember(text, tags, **metadata) |
Store a memory. Returns memory ID. |
observe(event) |
Update relationship + emotion. Events: reply_fast, reply_slow, no_reply, long_silence, affection, fight, apology, initiate, reject, long_message |
step_time(hours) |
Advance time โ OU decay on all dimensions |
tick(now, context) |
Full pipeline. Returns AffectiveResult. |
record_reply(**kwargs) |
Record user reply (passthrough to base) |
record_send() |
Record that we sent (passthrough to base) |
get_state() |
Snapshot of all 3 layers |
AffectiveResult
@dataclass
class AffectiveResult:
# Decision
should_send: bool
base_probability: float
# Memory
memory_trigger: str | None
memory_similarity: float
longing_boost: float
boosted_probability: float
# Relationship
relationship_stage: Stage
intimacy: float
conflict: float
# Emotion
emotional_state: EmotionalState
# Output
prompt: str
reason: str
Events
| Event | Description | Intimacy | Conflict |
|---|---|---|---|
reply_fast |
User replied quickly | +0.05 | -0.02 |
reply_slow |
User replied slowly | -0.02 | +0.01 |
no_reply |
User didn't reply | -0.05 | +0.03 |
long_silence |
No contact >24h | -0.10 | +0.05 |
affection |
User showed warmth | +0.10 | -0.05 |
fight |
Conflict | -0.15 | +0.20 |
apology |
Someone apologized | +0.05 | -0.15 |
initiate |
User initiated contact | +0.08 | -0.02 |
reject |
User rejected us | -0.12 | +0.10 |
Examples
Run the quickstarts:
# Memory triggers
python examples/quickstart.py
# Relationship state machine
python examples/quickstart_relationship.py
# VAD emotion engine
python examples/quickstart_emotion.py
# Full integration
python examples/quickstart_integrated.py
Tests
pip install -e ".[memory,test]"
pytest tests/ -v
62 tests covering all modules.
Theoretical Foundations
| Module | Theory | Reference |
|---|---|---|
| Memory | Sentence embeddings | Reimers & Gurevych, 2019 |
| Memory | Forgetting curve | Ebbinghaus, 1885 |
| Relationship | Hidden Markov Model | Rabiner, 1989 |
| Relationship | Ornstein-Uhlenbeck | Uhlenbeck & Ornstein, 1930 |
| Emotion | Circumplex Model | Russell, 1980 |
| Emotion | PAD Model | Mehrabian, 1996 |
| Base | Poisson Process | Poisson, 1837 |
| Base | Bayesian Inference | Bayes, 1763 |
| Base | Information Gain | Shannon, 1948 |
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 affective_longing-0.1.0.tar.gz.
File metadata
- Download URL: affective_longing-0.1.0.tar.gz
- Upload date:
- Size: 25.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc4e133f2397aa6e97dd95448df4d76b7cde86be295576b60c927e183a9d2f20
|
|
| MD5 |
f1babe32093f37ca78310f2b2b3fbb2d
|
|
| BLAKE2b-256 |
1d72da9f9040fab6aef67df37f4f82e958fef5cf0af5f6af8d36e129ea5b5e6b
|
File details
Details for the file affective_longing-0.1.0-py3-none-any.whl.
File metadata
- Download URL: affective_longing-0.1.0-py3-none-any.whl
- Upload date:
- Size: 23.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4c7ac9670ea0afa1c8f2597aab62ce1a55a0da0e795af1c6cba2400f6e03c7cb
|
|
| MD5 |
1f64b5df57366b9d32fd09aba42a066d
|
|
| BLAKE2b-256 |
c0a5b07b17e4cdf43d1b9421488a15d505f1b501aa759088b9553210b09da795
|