affective-longing 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- affective_longing-0.1.0/PKG-INFO +260 -0
- affective_longing-0.1.0/README.md +241 -0
- affective_longing-0.1.0/pyproject.toml +47 -0
- affective_longing-0.1.0/setup.cfg +4 -0
- affective_longing-0.1.0/src/affective_longing/__init__.py +47 -0
- affective_longing-0.1.0/src/affective_longing/emotion/__init__.py +18 -0
- affective_longing-0.1.0/src/affective_longing/emotion/engine.py +235 -0
- affective_longing-0.1.0/src/affective_longing/emotion/vad.py +116 -0
- affective_longing-0.1.0/src/affective_longing/engine.py +288 -0
- affective_longing-0.1.0/src/affective_longing/memory/__init__.py +7 -0
- affective_longing-0.1.0/src/affective_longing/memory/memory_store.py +100 -0
- affective_longing-0.1.0/src/affective_longing/memory/store.py +87 -0
- affective_longing-0.1.0/src/affective_longing/memory/trigger_engine.py +78 -0
- affective_longing-0.1.0/src/affective_longing/relationship/__init__.py +22 -0
- affective_longing-0.1.0/src/affective_longing/relationship/ou_process.py +94 -0
- affective_longing-0.1.0/src/affective_longing/relationship/stages.py +79 -0
- affective_longing-0.1.0/src/affective_longing/relationship/state_machine.py +397 -0
- affective_longing-0.1.0/src/affective_longing.egg-info/PKG-INFO +260 -0
- affective_longing-0.1.0/src/affective_longing.egg-info/SOURCES.txt +24 -0
- affective_longing-0.1.0/src/affective_longing.egg-info/dependency_links.txt +1 -0
- affective_longing-0.1.0/src/affective_longing.egg-info/requires.txt +9 -0
- affective_longing-0.1.0/src/affective_longing.egg-info/top_level.txt +1 -0
- affective_longing-0.1.0/tests/test_emotion.py +119 -0
- affective_longing-0.1.0/tests/test_integration.py +104 -0
- affective_longing-0.1.0/tests/test_memory.py +115 -0
- affective_longing-0.1.0/tests/test_relationship.py +149 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: affective-longing
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Emotional extension for AI companions โ memory triggers, relationship states, self-emotion.
|
|
5
|
+
Author-email: pear think <gangwang694@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/pearthink123/affective-longing
|
|
8
|
+
Project-URL: Repository, https://github.com/pearthink123/affective-longing
|
|
9
|
+
Keywords: ai,companion,emotion,memory,longing,relationship
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: revive-companion>=1.0.0
|
|
13
|
+
Requires-Dist: numpy>=1.23
|
|
14
|
+
Provides-Extra: memory
|
|
15
|
+
Requires-Dist: sentence-transformers>=3.0.0; extra == "memory"
|
|
16
|
+
Requires-Dist: chromadb>=0.5.0; extra == "memory"
|
|
17
|
+
Provides-Extra: test
|
|
18
|
+
Requires-Dist: pytest>=7.0; extra == "test"
|
|
19
|
+
|
|
20
|
+
# affective-longing ๐ง ๐ซ
|
|
21
|
+
|
|
22
|
+
**Emotional extension for AI companions โ beyond timing, into feeling.**
|
|
23
|
+
|
|
24
|
+
Built on [revive-companion](https://github.com/pearthink123/revive-companion) (Poisson timing + Bayesian inference).
|
|
25
|
+
|
|
26
|
+
## Architecture
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
30
|
+
โ AffectiveLonging โ
|
|
31
|
+
โ โ
|
|
32
|
+
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
|
|
33
|
+
โ โ Memory โ โ Relationship โ โ Emotion โ โ
|
|
34
|
+
โ โ โ โ โ โ โ โ
|
|
35
|
+
โ โ ChromaDB โ โ HMM โ โ VAD Model โ โ
|
|
36
|
+
โ โ Embeddings โ โ OU Process โ โ Valence โ โ
|
|
37
|
+
โ โ Similarity โ โ 6 Stages โ โ Arousal โ โ
|
|
38
|
+
โ โ โ โ โ โ Dominance โ โ
|
|
39
|
+
โ โโโโโโโโฌโโโโโโโโ โโโโโโโโฌโโโโโโโโ โโโโโโโโฌโโโโโโโโ โ
|
|
40
|
+
โ โ โ โ โ
|
|
41
|
+
โ โโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโ โ
|
|
42
|
+
โ โผ โ
|
|
43
|
+
โ tick() โ AffectiveResult โ
|
|
44
|
+
โ โ
|
|
45
|
+
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
|
46
|
+
โ โ revive-companion (base) โ โ
|
|
47
|
+
โ โ Poisson Process โ InfoGain โ Bayesian โ Decision โ โ
|
|
48
|
+
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
|
49
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Three Layers
|
|
53
|
+
|
|
54
|
+
### 1. Memory โ Past triggers present
|
|
55
|
+
|
|
56
|
+
Store conversations as embeddings. When current context matches past memories, longing probability gets a boost.
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
engine.remember("ไฝ ๅๆฌขไธ้จๅคฉ", tags=["weather"])
|
|
60
|
+
engine.remember("ๆไปฌ็ฌฌไธๆฌก็็ตๅฝฑๆฏใๆ้
็ฉฟ่ถใ", tags=["movie"])
|
|
61
|
+
|
|
62
|
+
# Later...
|
|
63
|
+
result = engine.tick(context="ไปๅคฉไธ้จไบ")
|
|
64
|
+
# โ Triggers "ไฝ ๅๆฌขไธ้จๅคฉ" with similarity 0.988
|
|
65
|
+
# โ Longing boost: +15%
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Theory:** [Sentence embeddings](https://arxiv.org/abs/1708.00055) (all-MiniLM-L6-v2) + cosine similarity. Memory decay via [Ebbinghaus forgetting curve](https://en.wikipedia.org/wiki/Forgetting_curve).
|
|
69
|
+
|
|
70
|
+
### 2. Relationship โ 6-stage lifecycle
|
|
71
|
+
|
|
72
|
+
Models relationship dynamics through discrete state transitions (HMM) + continuous emotional drift (Ornstein-Uhlenbeck process).
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
่ฟฝๆฑ โ ็่ โ ็ญๆ โ ๅนณ็จณ
|
|
76
|
+
โ โ
|
|
77
|
+
โโโโโ ไฟฎๅค โ ๅทๆ โโโโ
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
engine.observe("affection") # intimacy +0.10
|
|
82
|
+
engine.observe("fight") # conflict +0.20, may โ ๅทๆ
|
|
83
|
+
engine.step_time(hours=24) # OU decay toward baseline
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Theory:**
|
|
87
|
+
- **HMM:** Hidden states (relationship stages), observed events (user actions). Transition matrix modulated by intimacy/conflict levels.
|
|
88
|
+
- **Ornstein-Uhlenbeck:** Mean-reverting stochastic process. `dX = ฮธ(ฮผ - X)dt + ฯdW`. Models how intimacy/conflict drift toward baselines over time.
|
|
89
|
+
|
|
90
|
+
### 3. Emotion โ VAD model
|
|
91
|
+
|
|
92
|
+
AI companion's internal emotional state modeled as 3D vector (Valence, Arousal, Dominance). Mapped to 11 discrete emotions.
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
state = engine.emotion.current_state
|
|
96
|
+
# EmotionalState(๐ joy, V=+0.65, A=0.58, D=0.55)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
| Dimension | Range | Meaning |
|
|
100
|
+
|-----------|-------|---------|
|
|
101
|
+
| Valence | -1 to +1 | Unhappy โ Happy |
|
|
102
|
+
| Arousal | 0 to 1 | Calm โ Excited |
|
|
103
|
+
| Dominance | 0 to 1 | Submissive โ Dominant |
|
|
104
|
+
|
|
105
|
+
**Theory:** [Russell's Circumplex Model (1980)](https://psycnet.apa.org/record/1981-25703-001) + [Mehrabian's PAD model (1996)](https://psycnet.apa.org/record/1996-97463-000). OU process for time decay, event-driven bumps for state changes.
|
|
106
|
+
|
|
107
|
+
## Install
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Base (Poisson + Bayesian from revive-companion)
|
|
111
|
+
pip install affective-longing
|
|
112
|
+
|
|
113
|
+
# With memory support (sentence-transformers + chromadb)
|
|
114
|
+
pip install affective-longing[memory]
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Quick Start
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from affective_longing import AffectiveLonging
|
|
121
|
+
|
|
122
|
+
engine = AffectiveLonging(seed=42)
|
|
123
|
+
|
|
124
|
+
# 1. Store memories
|
|
125
|
+
engine.remember("ไฝ ๅๆฌขไธ้จๅคฉ", tags=["weather"])
|
|
126
|
+
engine.remember("ไฝ ่ฏด่ฟๆๅๆฌขๅ่่่็ณ", tags=["food"])
|
|
127
|
+
|
|
128
|
+
# 2. Observe events
|
|
129
|
+
engine.observe("reply_fast")
|
|
130
|
+
engine.observe("affection")
|
|
131
|
+
|
|
132
|
+
# 3. Let time pass
|
|
133
|
+
engine.step_time(hours=12)
|
|
134
|
+
|
|
135
|
+
# 4. Tick with context
|
|
136
|
+
result = engine.tick(context="ไปๅคฉไธ้จไบ")
|
|
137
|
+
|
|
138
|
+
print(f"Base probability: {result.base_probability:.1%}")
|
|
139
|
+
print(f"Memory trigger: {result.memory_trigger}")
|
|
140
|
+
print(f"Similarity: {result.memory_similarity:.3f}")
|
|
141
|
+
print(f"Boosted probability: {result.boosted_probability:.1%}")
|
|
142
|
+
print(f"Relationship: {result.relationship_stage.value}")
|
|
143
|
+
print(f"Emotion: {result.emotional_state.emoji} {result.emotional_state.emotion.value}")
|
|
144
|
+
|
|
145
|
+
if result.should_send:
|
|
146
|
+
send_message(result.prompt)
|
|
147
|
+
engine.record_send()
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## API Reference
|
|
151
|
+
|
|
152
|
+
### AffectiveLonging
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
engine = AffectiveLonging(
|
|
156
|
+
memory_persist_dir="./companion_memory_db", # Where to store embeddings
|
|
157
|
+
relationship_seed=None, # For reproducibility
|
|
158
|
+
emotion_seed=None,
|
|
159
|
+
**kwargs # Passed to PoissonLove
|
|
160
|
+
)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Methods:**
|
|
164
|
+
|
|
165
|
+
| Method | Description |
|
|
166
|
+
|--------|-------------|
|
|
167
|
+
| `remember(text, tags, **metadata)` | Store a memory. Returns memory ID. |
|
|
168
|
+
| `observe(event)` | Update relationship + emotion. Events: `reply_fast`, `reply_slow`, `no_reply`, `long_silence`, `affection`, `fight`, `apology`, `initiate`, `reject`, `long_message` |
|
|
169
|
+
| `step_time(hours)` | Advance time โ OU decay on all dimensions |
|
|
170
|
+
| `tick(now, context)` | Full pipeline. Returns `AffectiveResult`. |
|
|
171
|
+
| `record_reply(**kwargs)` | Record user reply (passthrough to base) |
|
|
172
|
+
| `record_send()` | Record that we sent (passthrough to base) |
|
|
173
|
+
| `get_state()` | Snapshot of all 3 layers |
|
|
174
|
+
|
|
175
|
+
### AffectiveResult
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
@dataclass
|
|
179
|
+
class AffectiveResult:
|
|
180
|
+
# Decision
|
|
181
|
+
should_send: bool
|
|
182
|
+
base_probability: float
|
|
183
|
+
|
|
184
|
+
# Memory
|
|
185
|
+
memory_trigger: str | None
|
|
186
|
+
memory_similarity: float
|
|
187
|
+
longing_boost: float
|
|
188
|
+
boosted_probability: float
|
|
189
|
+
|
|
190
|
+
# Relationship
|
|
191
|
+
relationship_stage: Stage
|
|
192
|
+
intimacy: float
|
|
193
|
+
conflict: float
|
|
194
|
+
|
|
195
|
+
# Emotion
|
|
196
|
+
emotional_state: EmotionalState
|
|
197
|
+
|
|
198
|
+
# Output
|
|
199
|
+
prompt: str
|
|
200
|
+
reason: str
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Events
|
|
204
|
+
|
|
205
|
+
| Event | Description | Intimacy | Conflict |
|
|
206
|
+
|-------|-------------|----------|----------|
|
|
207
|
+
| `reply_fast` | User replied quickly | +0.05 | -0.02 |
|
|
208
|
+
| `reply_slow` | User replied slowly | -0.02 | +0.01 |
|
|
209
|
+
| `no_reply` | User didn't reply | -0.05 | +0.03 |
|
|
210
|
+
| `long_silence` | No contact >24h | -0.10 | +0.05 |
|
|
211
|
+
| `affection` | User showed warmth | +0.10 | -0.05 |
|
|
212
|
+
| `fight` | Conflict | -0.15 | +0.20 |
|
|
213
|
+
| `apology` | Someone apologized | +0.05 | -0.15 |
|
|
214
|
+
| `initiate` | User initiated contact | +0.08 | -0.02 |
|
|
215
|
+
| `reject` | User rejected us | -0.12 | +0.10 |
|
|
216
|
+
|
|
217
|
+
## Examples
|
|
218
|
+
|
|
219
|
+
Run the quickstarts:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
# Memory triggers
|
|
223
|
+
python examples/quickstart.py
|
|
224
|
+
|
|
225
|
+
# Relationship state machine
|
|
226
|
+
python examples/quickstart_relationship.py
|
|
227
|
+
|
|
228
|
+
# VAD emotion engine
|
|
229
|
+
python examples/quickstart_emotion.py
|
|
230
|
+
|
|
231
|
+
# Full integration
|
|
232
|
+
python examples/quickstart_integrated.py
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Tests
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
pip install -e ".[memory,test]"
|
|
239
|
+
pytest tests/ -v
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
62 tests covering all modules.
|
|
243
|
+
|
|
244
|
+
## Theoretical Foundations
|
|
245
|
+
|
|
246
|
+
| Module | Theory | Reference |
|
|
247
|
+
|--------|--------|-----------|
|
|
248
|
+
| Memory | Sentence embeddings | [Reimers & Gurevych, 2019](https://arxiv.org/abs/1908.10084) |
|
|
249
|
+
| Memory | Forgetting curve | [Ebbinghaus, 1885](https://en.wikipedia.org/wiki/Forgetting_curve) |
|
|
250
|
+
| Relationship | Hidden Markov Model | [Rabiner, 1989](https://ieeexplore.ieee.org/document/18626) |
|
|
251
|
+
| Relationship | Ornstein-Uhlenbeck | [Uhlenbeck & Ornstein, 1930](https://journals.aps.org/pr/abstract/10.1103/PhysRev.36.823) |
|
|
252
|
+
| Emotion | Circumplex Model | [Russell, 1980](https://psycnet.apa.org/record/1981-25703-001) |
|
|
253
|
+
| Emotion | PAD Model | [Mehrabian, 1996](https://psycnet.apa.org/record/1996-97463-000) |
|
|
254
|
+
| Base | Poisson Process | [Poisson, 1837](https://en.wikipedia.org/wiki/Poisson_point_process) |
|
|
255
|
+
| Base | Bayesian Inference | [Bayes, 1763](https://en.wikipedia.org/wiki/Bayesian_inference) |
|
|
256
|
+
| Base | Information Gain | [Shannon, 1948](https://en.wikipedia.org/wiki/Information_gain) |
|
|
257
|
+
|
|
258
|
+
## License
|
|
259
|
+
|
|
260
|
+
MIT
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# affective-longing ๐ง ๐ซ
|
|
2
|
+
|
|
3
|
+
**Emotional extension for AI companions โ beyond timing, into feeling.**
|
|
4
|
+
|
|
5
|
+
Built on [revive-companion](https://github.com/pearthink123/revive-companion) (Poisson timing + Bayesian inference).
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
11
|
+
โ AffectiveLonging โ
|
|
12
|
+
โ โ
|
|
13
|
+
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
|
|
14
|
+
โ โ Memory โ โ Relationship โ โ Emotion โ โ
|
|
15
|
+
โ โ โ โ โ โ โ โ
|
|
16
|
+
โ โ ChromaDB โ โ HMM โ โ VAD Model โ โ
|
|
17
|
+
โ โ Embeddings โ โ OU Process โ โ Valence โ โ
|
|
18
|
+
โ โ Similarity โ โ 6 Stages โ โ Arousal โ โ
|
|
19
|
+
โ โ โ โ โ โ Dominance โ โ
|
|
20
|
+
โ โโโโโโโโฌโโโโโโโโ โโโโโโโโฌโโโโโโโโ โโโโโโโโฌโโโโโโโโ โ
|
|
21
|
+
โ โ โ โ โ
|
|
22
|
+
โ โโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโ โ
|
|
23
|
+
โ โผ โ
|
|
24
|
+
โ tick() โ AffectiveResult โ
|
|
25
|
+
โ โ
|
|
26
|
+
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
|
27
|
+
โ โ revive-companion (base) โ โ
|
|
28
|
+
โ โ Poisson Process โ InfoGain โ Bayesian โ Decision โ โ
|
|
29
|
+
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
|
30
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Three Layers
|
|
34
|
+
|
|
35
|
+
### 1. Memory โ Past triggers present
|
|
36
|
+
|
|
37
|
+
Store conversations as embeddings. When current context matches past memories, longing probability gets a boost.
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
engine.remember("ไฝ ๅๆฌขไธ้จๅคฉ", tags=["weather"])
|
|
41
|
+
engine.remember("ๆไปฌ็ฌฌไธๆฌก็็ตๅฝฑๆฏใๆ้
็ฉฟ่ถใ", tags=["movie"])
|
|
42
|
+
|
|
43
|
+
# Later...
|
|
44
|
+
result = engine.tick(context="ไปๅคฉไธ้จไบ")
|
|
45
|
+
# โ Triggers "ไฝ ๅๆฌขไธ้จๅคฉ" with similarity 0.988
|
|
46
|
+
# โ Longing boost: +15%
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Theory:** [Sentence embeddings](https://arxiv.org/abs/1708.00055) (all-MiniLM-L6-v2) + cosine similarity. Memory decay via [Ebbinghaus forgetting curve](https://en.wikipedia.org/wiki/Forgetting_curve).
|
|
50
|
+
|
|
51
|
+
### 2. Relationship โ 6-stage lifecycle
|
|
52
|
+
|
|
53
|
+
Models relationship dynamics through discrete state transitions (HMM) + continuous emotional drift (Ornstein-Uhlenbeck process).
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
่ฟฝๆฑ โ ็่ โ ็ญๆ โ ๅนณ็จณ
|
|
57
|
+
โ โ
|
|
58
|
+
โโโโโ ไฟฎๅค โ ๅทๆ โโโโ
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
engine.observe("affection") # intimacy +0.10
|
|
63
|
+
engine.observe("fight") # conflict +0.20, may โ ๅทๆ
|
|
64
|
+
engine.step_time(hours=24) # OU decay toward baseline
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Theory:**
|
|
68
|
+
- **HMM:** Hidden states (relationship stages), observed events (user actions). Transition matrix modulated by intimacy/conflict levels.
|
|
69
|
+
- **Ornstein-Uhlenbeck:** Mean-reverting stochastic process. `dX = ฮธ(ฮผ - X)dt + ฯdW`. Models how intimacy/conflict drift toward baselines over time.
|
|
70
|
+
|
|
71
|
+
### 3. Emotion โ VAD model
|
|
72
|
+
|
|
73
|
+
AI companion's internal emotional state modeled as 3D vector (Valence, Arousal, Dominance). Mapped to 11 discrete emotions.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
state = engine.emotion.current_state
|
|
77
|
+
# EmotionalState(๐ joy, V=+0.65, A=0.58, D=0.55)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
| Dimension | Range | Meaning |
|
|
81
|
+
|-----------|-------|---------|
|
|
82
|
+
| Valence | -1 to +1 | Unhappy โ Happy |
|
|
83
|
+
| Arousal | 0 to 1 | Calm โ Excited |
|
|
84
|
+
| Dominance | 0 to 1 | Submissive โ Dominant |
|
|
85
|
+
|
|
86
|
+
**Theory:** [Russell's Circumplex Model (1980)](https://psycnet.apa.org/record/1981-25703-001) + [Mehrabian's PAD model (1996)](https://psycnet.apa.org/record/1996-97463-000). OU process for time decay, event-driven bumps for state changes.
|
|
87
|
+
|
|
88
|
+
## Install
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Base (Poisson + Bayesian from revive-companion)
|
|
92
|
+
pip install affective-longing
|
|
93
|
+
|
|
94
|
+
# With memory support (sentence-transformers + chromadb)
|
|
95
|
+
pip install affective-longing[memory]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Quick Start
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from affective_longing import AffectiveLonging
|
|
102
|
+
|
|
103
|
+
engine = AffectiveLonging(seed=42)
|
|
104
|
+
|
|
105
|
+
# 1. Store memories
|
|
106
|
+
engine.remember("ไฝ ๅๆฌขไธ้จๅคฉ", tags=["weather"])
|
|
107
|
+
engine.remember("ไฝ ่ฏด่ฟๆๅๆฌขๅ่่่็ณ", tags=["food"])
|
|
108
|
+
|
|
109
|
+
# 2. Observe events
|
|
110
|
+
engine.observe("reply_fast")
|
|
111
|
+
engine.observe("affection")
|
|
112
|
+
|
|
113
|
+
# 3. Let time pass
|
|
114
|
+
engine.step_time(hours=12)
|
|
115
|
+
|
|
116
|
+
# 4. Tick with context
|
|
117
|
+
result = engine.tick(context="ไปๅคฉไธ้จไบ")
|
|
118
|
+
|
|
119
|
+
print(f"Base probability: {result.base_probability:.1%}")
|
|
120
|
+
print(f"Memory trigger: {result.memory_trigger}")
|
|
121
|
+
print(f"Similarity: {result.memory_similarity:.3f}")
|
|
122
|
+
print(f"Boosted probability: {result.boosted_probability:.1%}")
|
|
123
|
+
print(f"Relationship: {result.relationship_stage.value}")
|
|
124
|
+
print(f"Emotion: {result.emotional_state.emoji} {result.emotional_state.emotion.value}")
|
|
125
|
+
|
|
126
|
+
if result.should_send:
|
|
127
|
+
send_message(result.prompt)
|
|
128
|
+
engine.record_send()
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## API Reference
|
|
132
|
+
|
|
133
|
+
### AffectiveLonging
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
engine = AffectiveLonging(
|
|
137
|
+
memory_persist_dir="./companion_memory_db", # Where to store embeddings
|
|
138
|
+
relationship_seed=None, # For reproducibility
|
|
139
|
+
emotion_seed=None,
|
|
140
|
+
**kwargs # Passed to PoissonLove
|
|
141
|
+
)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Methods:**
|
|
145
|
+
|
|
146
|
+
| Method | Description |
|
|
147
|
+
|--------|-------------|
|
|
148
|
+
| `remember(text, tags, **metadata)` | Store a memory. Returns memory ID. |
|
|
149
|
+
| `observe(event)` | Update relationship + emotion. Events: `reply_fast`, `reply_slow`, `no_reply`, `long_silence`, `affection`, `fight`, `apology`, `initiate`, `reject`, `long_message` |
|
|
150
|
+
| `step_time(hours)` | Advance time โ OU decay on all dimensions |
|
|
151
|
+
| `tick(now, context)` | Full pipeline. Returns `AffectiveResult`. |
|
|
152
|
+
| `record_reply(**kwargs)` | Record user reply (passthrough to base) |
|
|
153
|
+
| `record_send()` | Record that we sent (passthrough to base) |
|
|
154
|
+
| `get_state()` | Snapshot of all 3 layers |
|
|
155
|
+
|
|
156
|
+
### AffectiveResult
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
@dataclass
|
|
160
|
+
class AffectiveResult:
|
|
161
|
+
# Decision
|
|
162
|
+
should_send: bool
|
|
163
|
+
base_probability: float
|
|
164
|
+
|
|
165
|
+
# Memory
|
|
166
|
+
memory_trigger: str | None
|
|
167
|
+
memory_similarity: float
|
|
168
|
+
longing_boost: float
|
|
169
|
+
boosted_probability: float
|
|
170
|
+
|
|
171
|
+
# Relationship
|
|
172
|
+
relationship_stage: Stage
|
|
173
|
+
intimacy: float
|
|
174
|
+
conflict: float
|
|
175
|
+
|
|
176
|
+
# Emotion
|
|
177
|
+
emotional_state: EmotionalState
|
|
178
|
+
|
|
179
|
+
# Output
|
|
180
|
+
prompt: str
|
|
181
|
+
reason: str
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Events
|
|
185
|
+
|
|
186
|
+
| Event | Description | Intimacy | Conflict |
|
|
187
|
+
|-------|-------------|----------|----------|
|
|
188
|
+
| `reply_fast` | User replied quickly | +0.05 | -0.02 |
|
|
189
|
+
| `reply_slow` | User replied slowly | -0.02 | +0.01 |
|
|
190
|
+
| `no_reply` | User didn't reply | -0.05 | +0.03 |
|
|
191
|
+
| `long_silence` | No contact >24h | -0.10 | +0.05 |
|
|
192
|
+
| `affection` | User showed warmth | +0.10 | -0.05 |
|
|
193
|
+
| `fight` | Conflict | -0.15 | +0.20 |
|
|
194
|
+
| `apology` | Someone apologized | +0.05 | -0.15 |
|
|
195
|
+
| `initiate` | User initiated contact | +0.08 | -0.02 |
|
|
196
|
+
| `reject` | User rejected us | -0.12 | +0.10 |
|
|
197
|
+
|
|
198
|
+
## Examples
|
|
199
|
+
|
|
200
|
+
Run the quickstarts:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
# Memory triggers
|
|
204
|
+
python examples/quickstart.py
|
|
205
|
+
|
|
206
|
+
# Relationship state machine
|
|
207
|
+
python examples/quickstart_relationship.py
|
|
208
|
+
|
|
209
|
+
# VAD emotion engine
|
|
210
|
+
python examples/quickstart_emotion.py
|
|
211
|
+
|
|
212
|
+
# Full integration
|
|
213
|
+
python examples/quickstart_integrated.py
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Tests
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
pip install -e ".[memory,test]"
|
|
220
|
+
pytest tests/ -v
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
62 tests covering all modules.
|
|
224
|
+
|
|
225
|
+
## Theoretical Foundations
|
|
226
|
+
|
|
227
|
+
| Module | Theory | Reference |
|
|
228
|
+
|--------|--------|-----------|
|
|
229
|
+
| Memory | Sentence embeddings | [Reimers & Gurevych, 2019](https://arxiv.org/abs/1908.10084) |
|
|
230
|
+
| Memory | Forgetting curve | [Ebbinghaus, 1885](https://en.wikipedia.org/wiki/Forgetting_curve) |
|
|
231
|
+
| Relationship | Hidden Markov Model | [Rabiner, 1989](https://ieeexplore.ieee.org/document/18626) |
|
|
232
|
+
| Relationship | Ornstein-Uhlenbeck | [Uhlenbeck & Ornstein, 1930](https://journals.aps.org/pr/abstract/10.1103/PhysRev.36.823) |
|
|
233
|
+
| Emotion | Circumplex Model | [Russell, 1980](https://psycnet.apa.org/record/1981-25703-001) |
|
|
234
|
+
| Emotion | PAD Model | [Mehrabian, 1996](https://psycnet.apa.org/record/1996-97463-000) |
|
|
235
|
+
| Base | Poisson Process | [Poisson, 1837](https://en.wikipedia.org/wiki/Poisson_point_process) |
|
|
236
|
+
| Base | Bayesian Inference | [Bayes, 1763](https://en.wikipedia.org/wiki/Bayesian_inference) |
|
|
237
|
+
| Base | Information Gain | [Shannon, 1948](https://en.wikipedia.org/wiki/Information_gain) |
|
|
238
|
+
|
|
239
|
+
## License
|
|
240
|
+
|
|
241
|
+
MIT
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "affective-longing"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Emotional extension for AI companions โ memory triggers, relationship states, self-emotion."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "pear think", email = "gangwang694@gmail.com" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["ai", "companion", "emotion", "memory", "longing", "relationship"]
|
|
16
|
+
dependencies = [
|
|
17
|
+
"revive-companion>=1.0.0",
|
|
18
|
+
"numpy>=1.23",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[project.optional-dependencies]
|
|
22
|
+
memory = [
|
|
23
|
+
"sentence-transformers>=3.0.0",
|
|
24
|
+
"chromadb>=0.5.0",
|
|
25
|
+
]
|
|
26
|
+
test = ["pytest>=7.0"]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/pearthink123/affective-longing"
|
|
30
|
+
Repository = "https://github.com/pearthink123/affective-longing"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools.packages.find]
|
|
33
|
+
where = ["src"]
|
|
34
|
+
|
|
35
|
+
[tool.ruff]
|
|
36
|
+
target-version = "py310"
|
|
37
|
+
line-length = 100
|
|
38
|
+
src = ["src", "tests"]
|
|
39
|
+
|
|
40
|
+
[tool.ruff.lint]
|
|
41
|
+
select = ["E", "F", "W", "I", "UP", "B"]
|
|
42
|
+
ignore = ["E501"]
|
|
43
|
+
|
|
44
|
+
[tool.mypy]
|
|
45
|
+
python_version = "3.10"
|
|
46
|
+
ignore_missing_imports = true
|
|
47
|
+
check_untyped_defs = true
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""
|
|
2
|
+
affective-longing: Emotional extension for AI companions.
|
|
3
|
+
|
|
4
|
+
Built on revive-companion, adds:
|
|
5
|
+
- Memory triggers (embedding similarity)
|
|
6
|
+
- Relationship state machine (HMM + OU process)
|
|
7
|
+
- AI self-emotion modeling (VAD model)
|
|
8
|
+
|
|
9
|
+
Three layers, one decision:
|
|
10
|
+
1. Memory โ past memories trigger present longing
|
|
11
|
+
2. Relationship โ 6-stage lifecycle with OU decay
|
|
12
|
+
3. Emotion โ VAD model for AI's internal state
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from .emotion import Emotion, EmotionEngine, EmotionEngineConfig, EmotionalState
|
|
16
|
+
from .engine import AffectiveLonging, AffectiveResult
|
|
17
|
+
from .memory import MemoryStore, TriggerEngine
|
|
18
|
+
from .relationship import (
|
|
19
|
+
Event,
|
|
20
|
+
OUProcess,
|
|
21
|
+
RelationshipStateMachine,
|
|
22
|
+
RelationshipState,
|
|
23
|
+
Stage,
|
|
24
|
+
TransitionConfig,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
# Core engine
|
|
29
|
+
"AffectiveLonging",
|
|
30
|
+
"AffectiveResult",
|
|
31
|
+
# Memory
|
|
32
|
+
"MemoryStore",
|
|
33
|
+
"TriggerEngine",
|
|
34
|
+
# Relationship
|
|
35
|
+
"Stage",
|
|
36
|
+
"RelationshipState",
|
|
37
|
+
"Event",
|
|
38
|
+
"RelationshipStateMachine",
|
|
39
|
+
"TransitionConfig",
|
|
40
|
+
"OUProcess",
|
|
41
|
+
# Emotion
|
|
42
|
+
"Emotion",
|
|
43
|
+
"EmotionalState",
|
|
44
|
+
"EmotionEngine",
|
|
45
|
+
"EmotionEngineConfig",
|
|
46
|
+
]
|
|
47
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Emotion module โ VAD model for AI companion's internal state.
|
|
3
|
+
|
|
4
|
+
Components:
|
|
5
|
+
- Emotion: Discrete emotion labels (joy, sadness, anger, etc.)
|
|
6
|
+
- EmotionalState: VAD snapshot with emotion label
|
|
7
|
+
- EmotionEngine: Manages emotional state with OU decay + events
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .engine import EmotionEngine, EmotionEngineConfig
|
|
11
|
+
from .vad import Emotion, EmotionalState
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"Emotion",
|
|
15
|
+
"EmotionalState",
|
|
16
|
+
"EmotionEngine",
|
|
17
|
+
"EmotionEngineConfig",
|
|
18
|
+
]
|