22 KiB
22 KiB
Architecture Overview
This document provides a comprehensive overview of the Daemon Boyfriend Discord bot architecture.
Table of Contents
- High-Level Architecture
- Directory Structure
- Core Components
- Data Flow
- Design Patterns
- Component Interaction Diagram
High-Level Architecture
┌─────────────────────────────────────────────────────────────────────────────┐
│ Discord API │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Discord Bot (bot.py) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ AIChatCog │ │ MemoryCog │ │ StatusCog │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌───────────────────────┐ ┌─────────────────┐ ┌─────────────────────────────┐
│ Core Services │ │ Living AI │ │ AI Providers │
│ ┌─────────────────┐ │ │ Services │ │ ┌─────────────────────┐ │
│ │ UserService │ │ │ ┌───────────┐ │ │ │ OpenAI Provider │ │
│ │ DatabaseService│ │ │ │ MoodSvc │ │ │ │ OpenRouter Provider│ │
│ │ ConversationMgr│ │ │ │ RelSvc │ │ │ │ Anthropic Provider │ │
│ │ SearXNGService │ │ │ │ FactSvc │ │ │ │ Gemini Provider │ │
│ └─────────────────┘ │ │ │ OpinionSvc│ │ │ └─────────────────────┘ │
└───────────────────────┘ │ │ StyleSvc │ │ └─────────────────────────────┘
│ │ ProactSvc │ │
│ │ AssocSvc │ │
│ │ SelfAware │ │
│ └───────────┘ │
└─────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ PostgreSQL Database │
│ ┌──────────────────────────────┐ ┌──────────────────────────────────────┐ │
│ │ Core Tables │ │ Living AI Tables │ │
│ │ users, guilds, conversations │ │ bot_states, user_relationships, │ │
│ │ messages, user_facts │ │ mood_history, scheduled_events │ │
│ └──────────────────────────────┘ └──────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
Directory Structure
daemon-boyfriend/
├── src/daemon_boyfriend/
│ ├── __main__.py # Entry point
│ ├── bot.py # Discord bot setup & cog loading
│ ├── config.py # Pydantic settings configuration
│ │
│ ├── cogs/ # Discord command handlers
│ │ ├── ai_chat.py # @mention response handler
│ │ ├── memory.py # Memory management commands
│ │ └── status.py # Bot status & health commands
│ │
│ ├── models/ # SQLAlchemy ORM models
│ │ ├── base.py # Base model with PortableJSON
│ │ ├── user.py # User, UserFact, UserPreference
│ │ ├── conversation.py # Conversation, Message
│ │ ├── guild.py # Guild, GuildMember
│ │ └── living_ai.py # All Living AI models
│ │
│ └── services/ # Business logic layer
│ ├── ai_service.py # AI provider factory
│ ├── database.py # Database connection management
│ ├── user_service.py # User CRUD operations
│ ├── conversation.py # In-memory conversation manager
│ ├── persistent_conversation.py # DB-backed conversations
│ ├── searxng.py # Web search integration
│ ├── monitoring.py # Health & metrics tracking
│ │
│ ├── providers/ # AI provider implementations
│ │ ├── base.py # Abstract AIProvider
│ │ ├── openai.py
│ │ ├── openrouter.py
│ │ ├── anthropic.py
│ │ └── gemini.py
│ │
│ └── [Living AI Services]
│ ├── mood_service.py
│ ├── relationship_service.py
│ ├── fact_extraction_service.py
│ ├── opinion_service.py
│ ├── communication_style_service.py
│ ├── proactive_service.py
│ ├── association_service.py
│ └── self_awareness_service.py
│
├── alembic/ # Database migrations
├── tests/ # Test suite
├── schema.sql # Database schema definition
├── docker-compose.yml # Docker deployment
└── requirements.txt # Python dependencies
Core Components
1. Discord Bot Layer
The bot uses discord.py with a cog-based architecture.
Entry Point (__main__.py)
- Creates the bot instance
- Initializes database connection
- Starts the Discord event loop
Bot Setup (bot.py)
- Configures Discord intents
- Auto-loads all cogs from
cogs/directory - Handles bot lifecycle events
Cogs
| Cog | Purpose | Trigger |
|---|---|---|
AIChatCog |
Main conversation handler | @mention |
MemoryCog |
User memory management | !setname, !remember, etc. |
StatusCog |
Health & metrics | !status (admin) |
2. Service Layer
Services contain all business logic and are designed to be:
- Stateless: No instance state, all state in database
- Async-first: All I/O operations are async
- Testable: Accept database sessions as parameters
Core Services
| Service | Responsibility |
|---|---|
AIService |
Factory for AI providers, prompt enhancement |
DatabaseService |
Connection pool, session management |
UserService |
User CRUD, facts, preferences |
ConversationManager |
In-memory conversation history |
PersistentConversationManager |
Database-backed conversations |
SearXNGService |
Web search for current information |
MonitoringService |
Health checks, metrics, error tracking |
Living AI Services (see Living AI documentation)
| Service | Responsibility |
|---|---|
MoodService |
Emotional state management |
RelationshipService |
User relationship tracking |
FactExtractionService |
Autonomous fact learning |
OpinionService |
Topic sentiment tracking |
CommunicationStyleService |
User style preferences |
ProactiveService |
Scheduled events & follow-ups |
AssociationService |
Cross-user memory linking |
SelfAwarenessService |
Bot statistics & reflection |
3. AI Provider Layer
Uses the Provider Pattern to support multiple AI backends.
┌────────────────────────────────────────────────────────────┐
│ AIService │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ get_provider() → returns appropriate AIProvider │ │
│ │ chat() → builds context and calls provider.generate │ │
│ └─────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ OpenAI Provider │ │ Anthropic Provider│ │ Gemini Provider │
│ (+ OpenRouter) │ │ │ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
4. Data Layer
Models (models/)
- SQLAlchemy ORM with async support
PortableJSONtype for PostgreSQL/SQLite compatibility- Timezone-aware UTC timestamps
Database (services/database.py)
- Async PostgreSQL via
asyncpg - Connection pooling
- Graceful fallback to in-memory when no database
Data Flow
Message Processing Flow
1. User sends @mention in Discord
│
▼
2. AIChatCog.on_message() receives event
│
▼
3. Get or create User via UserService
│
▼
4. Get or create Conversation
(PersistentConversationManager or ConversationManager)
│
▼
5. Build conversation history from messages
│
▼
6. [Optional] Check if web search needed
└─► SearXNGService.search() → add results to context
│
▼
7. Apply Living AI enhancements:
├─► MoodService.get_current_mood()
├─► RelationshipService.get_relationship()
├─► CommunicationStyleService.get_style()
└─► OpinionService.get_relevant_opinions()
│
▼
8. Build enhanced system prompt with all context
│
▼
9. AIService.chat() → Provider.generate()
│
▼
10. Post-response processing:
├─► MoodService.update_mood()
├─► RelationshipService.record_interaction()
├─► CommunicationStyleService.record_message()
├─► FactExtractionService.maybe_extract_facts()
└─► ProactiveService.check_for_events()
│
▼
11. Split response if > 2000 chars
│
▼
12. Send response(s) to Discord
Database Fallback Flow
┌─────────────────────────────────────────────────┐
│ Application Start │
└─────────────────────────────────────────────────┘
│
▼
┌────────────────────────┐
│ DATABASE_URL set? │
└────────────────────────┘
│ │
Yes No
│ │
▼ ▼
┌───────────────────┐ ┌───────────────────────┐
│ PostgreSQL Mode │ │ In-Memory Mode │
│ - Full persistence│ │ - ConversationManager │
│ - Living AI state │ │ - No persistence │
│ - User facts │ │ - Basic functionality │
└───────────────────┘ └───────────────────────┘
Design Patterns
1. Provider Pattern (AI Services)
Abstract base class with multiple implementations.
# base.py
class AIProvider(ABC):
@abstractmethod
async def generate(
self,
messages: list[Message],
system_prompt: str | None = None,
max_tokens: int = 1024,
temperature: float = 0.7,
) -> AIResponse:
pass
# openai.py
class OpenAIProvider(AIProvider):
async def generate(...) -> AIResponse:
# OpenAI-specific implementation
2. Factory Pattern (AIService)
Creates the appropriate provider based on configuration.
class AIService:
def __init__(self):
self.provider = self._create_provider()
def _create_provider(self) -> AIProvider:
match settings.ai_provider:
case "openai": return OpenAIProvider()
case "anthropic": return AnthropicProvider()
# ...
3. Repository Pattern (Services)
Services encapsulate data access logic.
class UserService:
@staticmethod
async def get_user(session: AsyncSession, discord_id: int) -> User | None:
result = await session.execute(
select(User).where(User.discord_id == discord_id)
)
return result.scalar_one_or_none()
4. Cog Pattern (Discord.py)
Modular command grouping.
class MemoryCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command(name="setname")
async def set_name(self, ctx, *, name: str):
# Command implementation
5. Graceful Degradation
System works with reduced functionality when components unavailable.
# Database fallback
if settings.database_url:
conversation_manager = PersistentConversationManager()
else:
conversation_manager = ConversationManager() # In-memory
# Feature toggles
if settings.living_ai_enabled and settings.mood_enabled:
mood = await MoodService.get_current_mood(session, guild_id)
else:
mood = None
Component Interaction Diagram
┌──────────────────────────────────────────┐
│ User Message │
└──────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ AIChatCog │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ UserService │ │ Conversation│ │ SearXNG │ │ AIService │ │
│ │ │ │ Manager │ │ Service │ │ │ │
│ │ get_user() │ │ get_history │ │ search() │ │ chat() ──────────┐ │ │
│ │ get_context │ │ add_message │ │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └──────────────────│──┘ │
│ │ │
│ ┌────────────────────────────────────────────────────────────────────┼────┐ │
│ │ Living AI Services │ │ │
│ │ │ │ │
│ │ ┌───────────┐ ┌──────────────┐ ┌───────────────┐ ┌────────────┐ │ │ │
│ │ │ MoodSvc │ │ Relationship │ │ CommStyleSvc │ │ OpinionSvc │ │ │ │
│ │ │ │ │ Svc │ │ │ │ │ │ │ │
│ │ │get_mood() │ │get_relation()│ │ get_style() │ │get_opinions│ │ │ │
│ │ │update() │ │record() │ │ record() │ │ update() │ │ │ │
│ │ └───────────┘ └──────────────┘ └───────────────┘ └────────────┘ │ │ │
│ │ │ │ │
│ │ ┌───────────────┐ ┌────────────────┐ ┌───────────────────────┐ │ │ │
│ │ │ FactExtract │ │ ProactiveSvc │ │ SelfAwarenessSvc │ │ │ │
│ │ │ │ │ │ │ │ │ │ │
│ │ │ extract() │ │ detect_events()│ │ get_stats() │ │ │ │
│ │ └───────────────┘ └────────────────┘ └───────────────────────┘ │ │ │
│ └────────────────────────────────────────────────────────────────────│────┘ │
│ │ │
└────────────────────────────────────────────────────────────────────────│──────┘
│
▼
┌──────────────────────────────────────────────┐
│ AI Provider │
│ (OpenAI / Anthropic / Gemini / OpenRouter) │
└──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Response │
└──────────────────────────────────────────────┘
Next Steps
- Living AI System - Deep dive into the personality system
- Services Reference - Detailed API documentation
- Database Schema - Complete schema documentation
- Configuration Reference - All configuration options
- Developer Guides - How to extend the system