Skip to main content

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."


Python 3.10+ License: MIT

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 git+https://github.com/pearthink123/revive-my-lover.git
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

可视化 AI 互动决策过程:渴望曲线、状态分布、发送历史。

# Install dashboard dependencies
pip install -e ".[dashboard]"

# Run dashboard
streamlit run dashboard.py

功能:

  • 🎲 渴望曲线 — Poisson 概率随时间变化
  • 🧠 状态分布 — Bayesian 推断的用户状态
  • 按小时分布 — 什么时候容易发消息
  • 📋 决策日志 — 每次决策的详细记录

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()

# 每隔一段时间检查
result = love.tick()
if result.should_send:
    send_message("想你了~")
    love.record_send()

# 收到回复后
love.record_reply(reply_speed=0.8, reply_length=0.6)

Telegram Bot

# 安装依赖
pip install python-telegram-bot

# 运行
python examples/telegram_bot.py --token YOUR_TOKEN --chat-id YOUR_CHAT_ID

Discord / Slack / 微信

同样的模式,只需替换发送函数:

# Discord
await channel.send(message)

# Slack
slack_client.chat_postMessage(channel=channel_id, text=message)

# 微信(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.


License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

revive_my_lover-0.9.0.tar.gz (48.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

revive_my_lover-0.9.0-py3-none-any.whl (44.5 kB view details)

Uploaded Python 3

File details

Details for the file revive_my_lover-0.9.0.tar.gz.

File metadata

  • Download URL: revive_my_lover-0.9.0.tar.gz
  • Upload date:
  • Size: 48.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for revive_my_lover-0.9.0.tar.gz
Algorithm Hash digest
SHA256 dd1fde068731ba51e86af86682247d1fbcf53afb032fa105ac95faef2ae68798
MD5 a19190400b949e85e050b0f248e96a92
BLAKE2b-256 e3bc6b2f8d5e3ad779901073ada03b007934af185a999971fe5177c0ac61cb53

See more details on using hashes here.

File details

Details for the file revive_my_lover-0.9.0-py3-none-any.whl.

File metadata

File hashes

Hashes for revive_my_lover-0.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 93225bcb25ac60134c6fdc944cd4c217e79cbafb4d6ec7305ffdd8ef1d9c5b24
MD5 3ef560ae7f3a76651b80eab9580d8f2c
BLAKE2b-256 1f9bddfdd930b06252bf27c3ddc1612e049ffe3ac746ed1df67da8e30b5ef3af

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page