Math models that make AI engagement feel human. Poisson timing + Bayesian state inference + Information theory.
Project description
revive-my-lover ๐
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 |
Quick Start
pip install revive-my-lover
from revive_my_lover 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_my_lover.adapters import OpenAIAdapter
adapter = OpenAIAdapter(config, api_key="sk-...")
# Anthropic / Claude
from revive_my_lover.adapters import AnthropicAdapter
adapter = AnthropicAdapter(config, api_key="sk-ant-...")
# Ollama / local models
from revive_my_lover.adapters import GenericAdapter
adapter = GenericAdapter(config, api_url="http://localhost:11434/v1/chat/completions")
# Run
from revive_my_lover.runner import Runner
runner = Runner(engine, adapter)
runner.run()
Architecture
revive-my-lover/
โโโ 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-my-lover
cd revive-my-lover
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_my_lover 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 emotional cost modeling, see the upcoming emotional extension (coming soon).
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 revive_my_lover-1.0.0.tar.gz.
File metadata
- Download URL: revive_my_lover-1.0.0.tar.gz
- Upload date:
- Size: 48.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34244e5ee4177ea40cb3b5f03267aed4fa053284ce8666d866f5ac598fd7dae0
|
|
| MD5 |
fb9b9470b96ae6e2e569e061c39f3316
|
|
| BLAKE2b-256 |
067bf710ee086838ef7c949e2fd266d03c196ded1111e46a5907b7e705890183
|
File details
Details for the file revive_my_lover-1.0.0-py3-none-any.whl.
File metadata
- Download URL: revive_my_lover-1.0.0-py3-none-any.whl
- Upload date:
- Size: 44.9 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 |
1386d7caac274f067baa0bad894361993d8a80689fcb68d92a375ca6d3bf433c
|
|
| MD5 |
c81f67441bbb24bdc82124de492a89fb
|
|
| BLAKE2b-256 |
514ccdaa665c868da12c458646bc67b873112ed28187b91e385ace6142951201
|