# Relationship-Aware Conversation System Design

**Date:** 2025-11-13
**Status:** Implemented
**Model:** GPT-5.1-2025-11-13

## Overview

This design implements a relationship-aware conversation system for BaoLife that makes NPC conversations feel realistic and appropriate based on the character's relationship to the player. The system ensures romantic partners are flirty, friends stay platonic, and professionals maintain boundaries.

## Problem Statement

The previous conversation system used generic prompts for all NPCs, resulting in:
- Romantic partners texting like coworkers
- Friends crossing into romantic territory inappropriately
- Bosses/teachers being too casual
- Loss of immersion and realism

All conversations felt samey regardless of relationship type.

## Goals

1. **Relationship-specific tones**: Romantic partners should be flirty/sensual, friends platonic, professionals appropriate
2. **Dynamic message length**: Short by default (texting-style), longer when context warrants
3. **Model flexibility**: Support GPT-5's native verbosity parameter + prompt fallback for other models
4. **Maintainability**: Easy to tune prompts per relationship type

## Architecture

### Component 1: Relationship Templates (`conversation_templates.py`)

A centralized repository of relationship-specific prompts defining tone and boundaries for each relationship type:

**Relationship Types:**
- **Romantic** (`partner`, `girlfriend`, `boyfriend`, `spouse`): Affectionate, flirty, sensual (tasteful)
- **Family** (`mother`, `father`, `sibling`): Nurturing, protective, appropriate parental/sibling dynamics
- **Friends** (`friend`): Casual, supportive, NO romantic undertones
- **Professional** (`boss`, `teacher`): Professional, respectful, maintains authority
- **Peers** (`classmate`, `coworker`): Friendly but not overly familiar
- **Distant** (`acquaintance`): Polite, surface-level

Each template includes:
```python
{
    'tone': 'romantic',  # Category
    'prompt': "Specific instructions for this relationship...",
    'boundaries': "Clear limits on behavior..."
}
```

**Key Function:**
```python
get_relationship_config(character) → dict
```
Returns the appropriate template based on character's `relationships` list.

### Component 2: Verbosity Detection (`detect_verbosity_level()`)

Analyzes conversation context to determine appropriate response length:

**Scoring System:**
- Has question mark: +2 points
- Long message (>100 chars): +2 points
- Multiple sentences: +1 point
- Deep topic keywords: +2 points

**Verbosity Levels:**
- **Low** (0-1 points): 30-60 tokens (~10-20 words) - Quick replies, banter
- **Medium** (2-3 points): 60-120 tokens (~20-40 words) - Normal conversation
- **High** (4+ points): 120-200 tokens (~40-65 words) - Deep topics, explanations

**Deep Topic Keywords:**
`why`, `how do you`, `what do you think`, `tell me about`, `feelings`, `relationship`, `future`, `dream`, `goal`, `problem`, `worried`, `scared`, `excited`

### Component 3: Prompt Fallback (`get_verbosity_prompt_hint()`)

For models without native verbosity parameter (non-GPT-5), injects length instructions directly into the prompt:

```python
{
    'low': "Keep your response very brief - one or two sentences max, like a quick text message (10-20 words).",
    'medium': "Respond naturally with a full thought, but stay concise like a text conversation (20-40 words).",
    'high': "Take your time to give a thoughtful, complete response. This topic deserves depth (40-65 words)."
}
```

### Component 4: Enhanced Prompt Builder

Updates in `getOpenAIResponse()` and `sendCharacterMessage()`:

1. **Detect relationship type** from `character.relationships[]`
2. **Load relationship template** via `get_relationship_config()`
3. **Analyze conversation context** via `detect_verbosity_level()`
4. **Build relationship-aware prompt:**
   ```
   "You are a real person having a text conversation..."
   + relationship_config['prompt']
   + relationship_config['boundaries']
   + affinity/familiarity context
   + verbosity hint (if needed)
   ```

5. **Configure API call:**
   ```python
   api_params = {
       'model': 'gpt-5.1-2025-11-13',
       'messages': messageList,
       'max_tokens': max_tokens,  # Dynamic: 60, 100, or 180
       'temperature': 0.8,
       'frequency_penalty': 1,
       'presence_penalty': 0.5
   }

   # GPT-5+ only
   if supports_verbosity:
       api_params['verbosity'] = verbosity_level  # 'low', 'medium', 'high'
   ```

## Model Selection: GPT-5.1-2025-11-13

**Why GPT-5.1:**
- **Native verbosity parameter**: `low`, `medium`, `high` - perfect for dynamic length control
- **Better instruction following**: Handles nuanced relationship boundaries better
- **400k context window**: Supports longer conversation history if needed
- **Improved coherence**: More natural, human-like responses

**Fallback Strategy:**
If GPT-5.1 unavailable or model changed in config:
- System detects via `model_name.startswith('gpt-5')`
- Injects verbosity hints into prompt instead
- Works with any OpenAI model (gpt-4o, gpt-4o-mini, etc.)

## Data Flow

```
User sends message
    ↓
detect_verbosity_level() analyzes context
    ↓ (verbosity_level, max_tokens)
get_relationship_config(character) loads template
    ↓ (relationship prompts & boundaries)
Build enhanced prompt with relationship awareness
    ↓
Check if model supports verbosity parameter
    ↓
  Yes (GPT-5+)              No (GPT-4o, etc.)
       ↓                           ↓
  Add to API params         Inject into prompt
       ↓                           ↓
        ↓←──────────────────────────←
                    ↓
      Call OpenAI API with dynamic settings
                    ↓
      Return contextually-appropriate response
```

## Implementation Files

### New Files
- **`ws/conversation_templates.py`**: Relationship template definitions

### Modified Files
- **`ws/conversationEvents.py`**: Added verbosity functions, updated prompts
- **`ws/events/conversations/npc_interactions.py`**: Mirror changes (duplicate file)
- **`ws/config.py`**: Changed model to `gpt-5.1-2025-11-13`

### Key Functions
```python
# New functions
detect_verbosity_level(conversation, character, player) → (level, tokens)
get_verbosity_prompt_hint(verbosity_level) → str
get_relationship_config(character) → dict

# Modified functions
async getOpenAIResponse(...) # Now relationship-aware
async sendCharacterMessage(...) # Now relationship-aware
```

## Example Scenarios

### Romantic Partner
**Context:** Player asks girlfriend about her day
**Template:** Romantic - "Be affectionate, playful, flirty..."
**Verbosity:** Low (quick question)
**Response:** "Work was boring without you babe 😘 Miss your face. Wanna do something tonight?"

### Boss
**Context:** Player asks boss about project deadline
**Template:** Professional - "Stay professional, business-focused..."
**Verbosity:** Medium (work topic)
**Response:** "The deadline is Friday at 5pm. Make sure you complete the QA checklist before submitting. Let me know if you need resources."

### Friend - Deep Topic
**Context:** Player: "I've been feeling really stressed about my future lately, what do you think I should do?"
**Template:** Friend - "Be supportive, casual, NO romantic undertones..."
**Verbosity:** High (deep topic + question)
**Response:** "Hey, I totally get that. Future stuff is scary. But you're smart and you've got time to figure it out. What's stressing you most? Maybe we can break it down together? You know I'm here for you."

## Benefits

1. **Immersion**: Conversations feel realistic and appropriate
2. **Flexibility**: Easy to add new relationship types or tune existing ones
3. **Performance**: Dynamic token limits optimize cost
4. **Maintainability**: Centralized templates, single source of truth
5. **Future-proof**: Works with any model via fallback strategy

## Testing Strategy

1. **Relationship Type Coverage**: Test each template with appropriate scenarios
2. **Verbosity Detection**: Verify short vs. deep topic responses
3. **Boundary Enforcement**: Ensure friends don't flirt, bosses stay professional
4. **Model Flexibility**: Test with verbosity parameter and without (fallback)
5. **Edge Cases**: No relationships defined, unknown relationship type

## Future Enhancements

1. **Relationship progression**: Adjust prompts as affinity/familiarity changes
2. **Contextual mood**: Factor in player/character mood/stress
3. **Time-of-day awareness**: Different tone for late-night vs. morning messages
4. **Dynamic boundaries**: Adjust based on game progress (dating → engaged → married)
5. **Additional models**: Support Anthropic Claude, other providers

## Configuration

**Environment Variables:**
```bash
CONVERSATION_MODEL_PROVIDER=openai
CONVERSATION_MODEL_NAME=gpt-5.1-2025-11-13
OPENAI_API_KEY=your_api_key_here
```

**To use different model:**
Change `CONVERSATION_MODEL_NAME` in `.env` or `config.py`
- GPT-5+: Native verbosity support
- Others: Automatic fallback to prompt-based hints

## Success Metrics

- **Realism**: Do conversations feel authentic for each relationship type?
- **Boundaries**: Are professional/family/friend boundaries maintained?
- **Romance**: Are romantic conversations appropriately flirty/intimate?
- **Length**: Do responses match context (short for banter, longer for depth)?
- **Cost**: Is token usage optimized via dynamic limits?

## Rollout

✅ **Phase 1**: Implementation (Complete)
- Created templates
- Added verbosity detection
- Updated prompt builders
- Configured GPT-5.1

⏭️ **Phase 2**: Testing
- Verify each relationship type
- Test verbosity detection
- Validate boundary enforcement

⏭️ **Phase 3**: Tuning
- Adjust prompts based on feedback
- Fine-tune verbosity thresholds
- Optimize token limits

## Related Documentation

- Original conversation system: `ws/conversationEvents.py`
- Character management: `ws/character/character_manager.py`
- Relationship system: `ws/relationships/relationship_manager.py`
