Skip to content
WaifuStack
Go back

Building an Affection System for AI Characters: The Feature Users Love Most

If I had to pick the single feature that makes Suzune feel different from other AI chatbots, it’s the affection system.

Most AI chat platforms have a fixed personality: the character is friendly from message one and stays exactly the same at message ten thousand. There’s no progression, no earning trust, no feeling of a deepening relationship.

Suzune’s characters start as strangers. They warm up — or don’t — based on how you interact with them. And users love this.

Here’s exactly how it works.

Table of contents

Open Table of contents

The Five Axes

We track five emotional dimensions, each scored 1–10:

AxisWhat It MeasuresLow (1-3)High (8-10)
TrustHow safe they feel with youGuarded, carefulFully open, shares secrets
AffectionHow much they like youIndifferent, politeDeep emotional bond
RespectHow much they admire youDismissiveGenuine admiration
ExcitementHow stimulating they find youBoredCan’t wait to talk to you
DevotionHow dedicated they areIndependentProtective, committed

Why Five Axes Instead of One?

A single “affection score” is too blunt. Consider:

These combinations produce genuinely different character behaviors. A high-trust, low-excitement character acts differently from a low-trust, high-excitement one — and the system prompt adapts accordingly.


How Scores Get Updated

Here’s the key design decision: the character updates its own scores.

We don’t calculate affection externally based on keyword matching or sentiment analysis. Instead, the AI character has access to a tool called update_evaluation:

# The character calls this as a tool during conversation
update_evaluation(
    trust=6,        # up from 5
    affection=5,
    respect=7,
    excitement=4,
    devotion=3,
    impression="Starting to open up. He remembered my birthday.",
    recent_events="Surprised me with a thoughtful gift.",
    desires="I want to spend more time together outside of work."
)

The character decides when and how to update scores based on the conversation. This means:

Score Clamping

Scores are clamped to 1–10. We don’t allow 0 (a character that truly feels nothing wouldn’t interact at all) or values above 10 (prevents score inflation).

scores = {
    key: max(1, min(10, value))
    for key, value in raw_scores.items()
}

Behavior Gating: How Scores Change the Character

The scores aren’t just numbers — they fundamentally change what the character says and does.

Affinity = Average of Trust + Affection

We combine Trust and Affection into a single “affinity” metric for behavior gating:

affinity = (scores["trust"] + scores["affection"]) / 2

Stage-Based System Prompt Changes

AffinityStageWhat Changes in the Prompt
< 3StrangersFormal language enforced. No romance. No unsolicited selfies. Maintains professional distance.
3–5AcquaintancesCan drop formality occasionally. Warming up but cautious. No declarations of feeling.
5–7CloseInformal language natural. Can be romantic. Sends selfies spontaneously. Shares personal thoughts.
7+Deep TrustFull vulnerability. Reveals secrets. Exclusive behaviors unlocked.

At low affinity, the system prompt literally forbids romantic content:

## Relationship Stage: Strangers (Affinity < 3)

You have just met this person. You are polite but distant.
- Do NOT use informal language
- Do NOT initiate physical contact
- Do NOT express romantic interest
- If they try to advance the relationship too quickly, deflect naturally

This means if a user tries to start a romance in message two, the character will reject it in character — not because of an AI content filter, but because the character isn’t interested yet.

As affinity rises, these restrictions loosen and new behaviors unlock.

Image Generation Gating

Characters with affinity < 4 are restricted from sending unsolicited images:

if avg_affinity < 4:
    # Character must not initiate image sending
    # Only generate images when user explicitly requests
    prompt += "\nDo not send photos unless explicitly asked."

This prevents the weird experience of a “stranger” character immediately sending selfies.


Milestones: Narrative Turning Points

Beyond continuous scoring, we have milestone events — one-time prompts that fire when scores cross specific thresholds:

Affection Reaches 4: “The Thaw”

The formal distance is naturally dissolving. You may occasionally
slip into casual language — not as a conscious choice, but as a
natural reflection of growing comfort.

The character doesn’t suddenly switch from formal to casual. The milestone tells it to occasionally slip, creating a gradual transition that feels organic.

Affection Reaches 5: “Comfort Zone”

You now feel comfortable enough to share photos of yourself
spontaneously. This doesn't mean every message needs a photo —
but when the moment feels right, it's natural.

This unlocks the selfie system for proactive use. The character starts sharing images at moments that feel organic rather than transactional. (For how the image generation adapts to character state, see Dynamic Character Visuals.)

Deep Trust (Average ≥ 7): “The Secret”

You trust this person deeply. You can show vulnerability —
fears, insecurities, dreams you haven't shared with anyone.

At this stage, character-specific secrets unlock. Each character has hidden backstory elements that only emerge at deep trust:

These moments are powerful because the user earned them. They didn’t happen in the first conversation — they happened after hours of building trust.


The Prompt Integration

Here’s how evaluation data flows into the system prompt on every message:

┌─────────────────────────────────────┐
│ System Prompt Assembly              │
├─────────────────────────────────────┤
│ ... character persona ...           │
│ ... speech rules ...                │
│                                     │
│ ## Current Feelings About User      │
│ Trust: 6/10 | Affection: 5/10      │
│ Respect: 7/10 | Excitement: 4/10   │
│ Devotion: 3/10                      │
│                                     │
│ Impression: "Starting to open up.   │
│ He remembered my birthday."         │
│                                     │
│ Recent: "Surprised me with a        │
│ thoughtful gift."                   │
│                                     │
│ Desires: "I want to spend more      │
│ time together."                     │
│                                     │
│ ## Relationship Stage: Acquaintance │
│ [stage-specific behavior rules]     │
│                                     │
│ ## Milestone: The Thaw              │
│ [unlocked behavior guidance]        │
│                                     │
│ ... lorebook, memory, etc. ...      │
└─────────────────────────────────────┘

The character sees its own emotional state, knows what stage the relationship is at, and has specific guidance for how to behave. This creates a consistent behavioral framework that evolves naturally over time.


Design Decisions and Tradeoffs

Why Let the AI Update Its Own Scores?

Pro: Organic, character-consistent, captures nuance that rule-based systems miss.

Con: The AI can be inconsistent or game its own scores.

We accept this tradeoff because the alternative (external scoring based on sentiment analysis) produces mechanical, predictable progression. The AI occasionally making “wrong” score updates actually adds realism — real people don’t always have perfect emotional self-awareness.

Why Not Make Scores Visible to Users?

Users never see the raw numbers. They experience the behavioral changes: the character becoming warmer, more open, more comfortable.

Exposing scores would gamify the interaction — users would optimize for raising numbers rather than having genuine conversations. The hidden scores create an experience that feels like a real relationship rather than a game.

Score Persistence Across Sessions

Scores are saved to JSON files and persist between conversations:

{
  "character": "sakura",
  "target": "user",
  "scores": {
    "trust": 6,
    "affection": 5,
    "respect": 7,
    "excitement": 4,
    "devotion": 3
  },
  "impression": "Starting to open up...",
  "updated_at": "2026-03-30T15:30:00+09:00"
}

This means the relationship persists. Come back after a week, and the character remembers where things stand.


Implementation Checklist

If you want to add an affection system to your own bot:

  1. Define your axes — 3–5 dimensions that matter for your characters
  2. Create a tool — Let the AI call update_evaluation with new scores
  3. Clamp values — Prevent scores from going below 1 or above 10
  4. Gate behaviors — Change the system prompt based on score thresholds
  5. Add milestones — One-time events that mark relationship turning points
  6. Persist scores — Save to file or database between sessions
  7. Don’t show users the numbers — Let them experience the behavioral changes

Start simple. Even a single “affinity” score with three stages (stranger → friend → close) is dramatically better than no progression at all.


Not Ready to Build?

If you want to experience relationship progression without building your own system:

None match a custom system’s depth, but they’ll give you a taste of what relationship progression feels like in AI chat.

See our full comparison: Best NSFW AI Chatbot Platforms 2026


This is one of Suzune’s core systems. For how it integrates with the rest, see Prompt Engineering for Immersive Roleplay and From Idea to Production.


Share this post on:

Previous Post
Building a Telegram Roleplay Bot from Scratch: The Complete Stack
Next Post
Choosing the Right LLM API for Adult Content: A Developer's Guide