revive-companion 💘
A probabilistic engagement engine for AI companions.
Not "engaged → send more". Instead: "infer what the user is doing → decide if you should."
English | 中文
The Problem
AI companions are either rigid (fixed schedules) or random (no memory). Neither feels human.
The Solution
A probabilistic engine that decides when and whether to reach out:
| Stage | Module | Question | Answer |
|---|---|---|---|
| 🎲 Timing | Poisson process | When to consider? | Randomized like real "thinking of you" |
| 📊 Value | Information theory | Is this worth it? | Skip if you already know user's state |
| 🧠 State | Bayesian inference | What's user doing? | Infer hidden state → decide accordingly |
🧠💫 Want more? Let your AI companion truly remember, evolve relationships, and have emotional states.
→ affective-longing — Memory triggers + Relationship state machine + AI self-emotion (VAD model)
pip install affective-longing[memory]
Quick Start
pip install revive-companion
from revive_companion import PoissonLove
love = PoissonLove()
result = love.tick()
if result.should_send:
send_message(result.prompt)
love.record_send()
# After user responds
love.record_reply(reply_speed=0.8, reply_length=0.6)
How It Decides
The engine infers the user's hidden state from observations:
| Inferred State | Utility | Decision |
|---|---|---|
| 🗣️ Chatting | 0.2 | ❌ Don't interrupt |
| 💻 Idle online | 0.7 | ✅ Good time to reach out |
| 💼 Busy | 0.1 | ❌ Don't bother |
| 😴 Sleeping | 0.0 | ❌ Never send |
| 🚶 Away | 0.3 | ⏳ Maybe later |
| 🆘 Needing | 0.9 | ✅ Check in! |
No more "engaged → send more". Now it's: "user is probably busy → don't bother" or "user might need care → reach out".
Use Any AI Backend
# OpenAI / GPT
from revive_companion.adapters import OpenAIAdapter
adapter = OpenAIAdapter(config, api_key="sk-...")
# Anthropic / Claude
from revive_companion.adapters import AnthropicAdapter
adapter = AnthropicAdapter(config, api_key="sk-ant-...")
# Ollama / local models
from revive_companion.adapters import GenericAdapter
adapter = GenericAdapter(config, api_url="http://localhost:11434/v1/chat/completions")
# Run
from revive_companion.runner import Runner
runner = Runner(engine, adapter)
runner.run()
Architecture
revive-companion/
├── love.py # Unified API (start here)
├── core/
│ ├── engine.py # Poisson dice + probability dynamics
│ ├── config.py # YAML config
│ └── models.py # Data structures
├── bayesian/
│ ├── core.py # State estimation + send utility
│ └── learner.py # Online learning from observations
├── info_gain/
│ ├── core.py # Entropy × resolution potential
│ └── sources.py # Silence, novelty, conversation state
├── control/
│ ├── pid.py # PID controller (standalone use)
│ └── signal.py # Pluggable signal framework
└── adapters/
├── openai.py # OpenAI / GPT
├── anthropic.py # Anthropic / Claude
└── generic.py # Ollama, HTTP, shell command
How It Works
The Math
Each tick, the engine computes hit probability:
P(hit) = 1 - e^(-λt)
Where λ = longing rate, t = time interval. Base: ~7.2% per 30-minute check.
Probability Dynamics
| Event | Probability | Why |
|---|---|---|
| Miss (no hit) | +8% | Longing builds |
| Hit → Hold | +8% | Longing suppressed |
| Hit → Send | Reset to 7.2% | Longing satisfied |
The Curve
Over a night (midnight → 8am):
- 16 checks, all held
- Probability: 7% → 15% → 30% → 55% → 80% → 95%
- This IS the longing — quantified, recorded, real
Configuration
engagement:
lambda_rate: 0.15 # Base longing rate
check_interval_minutes: 30 # Dice roll frequency
growth_factor: 0.08 # How fast longing grows
max_probability: 0.95 # Cap
min_interval_hours: 1.0 # Anti-spam cooldown
adjudication:
quiet_hours:
start: "00:00"
end: "08:00"
normal_send_probability: 0.7
persona:
name: Companion
tone: warm-brief
context: "You are a caring companion checking in on your person."
Dashboard
Visualize the AI engagement decision process: longing curves, state distributions, and send history.
# Install dashboard dependencies
pip install -e ".[dashboard]"
# Run dashboard
streamlit run dashboard.py
Features:
- 🎲 Longing Curve — Poisson probability over time
- 🧠 State Distribution — Bayesian-inferred user state
- ⏰ Hourly Pattern — When messages are most likely sent
- 📋 Decision Log — Detailed record of each decision
Demos
git clone https://github.com/pearthink123/revive-companion
cd revive-companion
pip install -e .
PYTHONPATH=src python examples/quickstart.py # Basic simulation
PYTHONPATH=src python examples/bayesian_demo.py # State inference
PYTHONPATH=src python examples/bayesian_learning_demo.py # Online learning
PYTHONPATH=src python examples/info_gain_demo.py # Information gain
PYTHONPATH=src python examples/integration_example.py # Smart notifier
Integration
Simple Integration (Any Bot)
from revive_companion import PoissonLove
love = PoissonLove()
# Check periodically
result = love.tick()
if result.should_send:
send_message("Thinking of you~")
love.record_send()
# When user replies
love.record_reply(reply_speed=0.8, reply_length=0.6)
Telegram Bot
# Install dependency
pip install python-telegram-bot
# Run
python examples/telegram_bot.py --token YOUR_TOKEN --chat-id YOUR_CHAT_ID
Discord / Slack / WeChat
Same pattern, just swap the send function:
# Discord
await channel.send(message)
# Slack
slack_client.chat_postMessage(channel=channel_id, text=message)
# WeChat (itchat)
itchat.send(message, toUserName=friend_name)
Testing
# Install test dependencies
pip install -e ".[test]"
# Run all tests
pytest tests/ -v
124 tests covering:
- 🎲 Poisson engine (determinism, growth, timing)
- 🧠 Bayesian inference (state estimation, likelihood, learning)
- 📊 Information gain (decay, thresholds)
- 💘 Unified API (full pipeline)
Consent & Safety
This library is designed for respectful AI engagement. Please use it responsibly:
Built-in Protections
- Quiet hours: No messages during configured sleep periods
- Minimum interval: Anti-spam cooldown between messages
- State inference: Won't bother users who are busy or sleeping
- Utility threshold: Conservative default (0.5) — only sends when appropriate
Best Practices
- ✅ Opt-in: Users should explicitly enable proactive messaging
- ✅ Easy disable: Users must be able to turn it off at any time
- ✅ Transparency: Users should know the AI can initiate contact
- ✅ No emotional manipulation: Don't use this to create dependency
- ❌ No unsolicited contact: Don't message users who didn't opt in
- ❌ No persistence: Respect when users want to be left alone
Default Behavior
- Messages are never sent during quiet hours (default: 00:00-08:00)
- At least 1 hour between messages (configurable)
- High engagement does not mean more messages (unlike simple linear models)
- The engine infers state before deciding, not just response speed
Why "Poisson"?
The Poisson process models events that happen independently at a constant average rate — like neurons firing, or "thinking about someone."
It's not random chaos. It's not rigid scheduling. It's structured spontaneity — the mathematical model of genuine, organic missing someone.
What's Next
This is the stable base — focused on smart timing, not deep emotion.
For memory-triggered longing, relationship state machines, and AI self-emotion modeling, see:
→ affective-longing — Emotional extension with 3 layers (Memory + Relationship + Emotion)
License
MIT
Release files for revive-companion 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| revive_companion-2.0.0.tar.gz | 48.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| revive_companion-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 94.6 kB
Release files / revive_companion-2.0.0.tar.gz
| Download URL | revive_companion-2.0.0.tar.gz |
|---|---|
| Size | 48.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2e0d35cbe72a2683491a71b9d9b072dff88d9634c5b8c0cdd1ed30db35e978c5
|
|
BLAKE2b-256 checksum How to use checksums |
d6d0a83436b80168df923b506fc265ef2b2d7d1fbe4d3bdbd7f15ecf003eeb59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Release files / revive_companion-2.0.0-py3-none-any.whl
| Download URL | revive_companion-2.0.0-py3-none-any.whl |
|---|---|
| Size | 45.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2ee21e3d7c90f9b6eadb57338a8c0abe90baddd660c38512d5be1d050d5327d0
|
|
BLAKE2b-256 checksum How to use checksums |
1485e8f7af5acefe04578eb6863b03c5c323cfa9ee8ff224a76f6c7ab0556718
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|